Weak linking to support previous iOS versions - iphone

I'm trying to support older iOS versions in my app. I initially thought I only have to set those frameworks to "weak linking" that are not present in the older OS, e.g. the iAd framework. And then make sure that I don't call unsupported APIs in the code. However, when I try to run the app (which is compiled with the most recent framework) in the old simulator, it crashes during startup with a message similar to
18/07/2010 11:07:29 UIKitApplication:xxxxx[0xe006][5729] dyld: Symbol not found: _OBJC_CLASS_$_NSAssertionHandler
18/07/2010 11:07:29 UIKitApplication:xxxxx[0xe006][5729] Referenced from: xxxxx/Applications/23CE4978-D25F-4DB4-A486-0730EBBB501B/xxxxx.app/xxxxx
18/07/2010 11:07:29 UIKitApplication:xxxxx[0xe006][5729] Expected in: /Xcode3.1.4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
18/07/2010 11:07:29 UIKitApplication:xxxxx[0xe006][5729] in xxxxx/Applications/23CE4978-D25F-4DB4-A486-0730EBBB501B/xxxxx.app/xxxxx
After setting all frameworks to weak linking, I still get an error message:
18/07/2010 11:33:32 UIKitApplication:xxxxx[0xc4a7][8204] dyld: Symbol not found: __objc_empty_vtable
18/07/2010 11:33:32 UIKitApplication:xxxxx[0xc4a7][8204] Referenced from: xxxxx/Applications/23CE4978-D25F-4DB4-A486-0730EBBB501B/xxxxx.app/xxxxx
18/07/2010 11:33:32 UIKitApplication:xxxxx[0xc4a7][8204] Expected in: /usr/lib/libobjc.A.dylib
What am I doing wrong?

I think I found the solution (please can someone confirm this?):
You cannot use the simulator to test if your apps run with a previous iOS version. It only works on the device, according to Apple:
iPhone OS Note: Mac OS X v10.6 does not support using iPhone
Simulator SDKs prior to version 3.0.
In addition, when building with the
simulator SDKs, the binary runs only
on the same OS version as the SDK, not
on earlier or later versions.
This seems really dull. How am I supposed to test backwards compatibility without having one physical iPhone for each SDK version? Not good.

You can't use the new class directly if you want to support old platforms. Instead, you use NSClassFromString like so:
class myClass = NSClassFromString(#"NSCoolNewClass");
if (myClass)
//do stuff

Related

coreImage iOS 4.3.3 crash

guys, I have iOS app, which running good on ios5.0, but on 4.3.3 it's crashing and writing this to console:
dyld: Library not loaded: /System/Library/Frameworks/CoreImage.framework/CoreImage
Referenced from: /Users/IvanTrufanov/Library/Application Support/iPhone Simulator/4.3.2/Applications/99C63A08-CC3E-49B7-A27D-1352D61C7C4F/habr.app/habr
Reason: image not found
Have you any ideas? What can be reason?
Core Image is only available with iOS 5.
https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/CoreImaging/ci_intro/ci_intro.html
As others note CoreImage requires iOS 5+. But you can still use CoreImage in apps supporting iOS 4.3 and below by weak linking against the framework.
To do this go to your project's build phases, find the "CoreImage.framework" reference and change the optional/required flag to optional.
Of course the CoreImage API won't be available prior to iOS 5, so you'll want to check the OS version before making any framework calls. You might find the following macros handy: https://stackoverflow.com/a/5337804/82169

iPad Simulator (4.3) crashes with dyld error

I'm running an application in an iPad Simulator (4.3) that crashes due to a missing symbol error:
dyld: Symbol not found: _OBJC_CLASS_$_NSMetadataQuery
Referenced from: /Users/Me/Library/Application Support/iPhone Simulator/4.3.2/Applications/B13BE6DF-61B9-4C23-98E7-BEC72330FF19/iPad.app/iPad
Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
in /Users/Me/Library/Application Support/iPhone Simulator/4.3.2/Applications/B13BE6DF-61B9-4C23-98E7-BEC72330FF19/iPad.app/iPad
At what point in the launch process does this error occur? I don't seem to be actually executing any code - I have placed breakpoints at both the locations where this class would be instantiated (which is never executed when version is < 5.0) and at the delegate method applicationWillFinishLaunching:
But, the crash occurs before either points are hit.
I know that the underlying issue is that the NSMetadataQuery class was added in iOS 5.0, but I would of course like to maintain backwards-compatibility with earlier versions. (I'm using the proper NSClassFromString calls.)
I have an iPhone application which uses NSMetadataQuery on iOS 5.0, and skips it if running 4.3 or lower, and works properly in the simulator. Thus, I'm confused as to why this particular program crashes.
Does the NSMetadataQuery class actually exist in the iPhone version of iOS 4.2 and 4.3, but not in the iPad version? (And the API simply wasn't exposed until iOS 5.0?)
The underlying issue was that the Foundation framework was strongly-linked in the iPad version of the application (that was crashing) and was weakly-linked in the iPhone version. (Which allowed the iPhone version to run without requiring those classes at linking time. Of course, calling/instantiating any of those classes on 4.X versions of the iPhone simulator would have similarly crashed.)
Problem was solved by changing (under the Project Info in Xcode) the dependency option of the Foundation.framework from required to optional.

Is ARC really supported in iOS 4? The iOS 4.2 SDK is missing ARC-related symbols at linking time

I've read and heard since ARC was first announced that it was a compile-time thing and would be backwards-compatible with iOS 4. I have successfully refactored my project to ARC using Xcode 4.2's automatic refactoring, and when compiled against the iOS 5.0 SDK, it works fine. However, if I try to compile against my iOS 4.2 SDK, it fails at link time, missing the following symbols:
_objc_retainAutoreleaseReturnValue
_objc_autoreleaseReturnValue
_objc_storeStrong
_objc_retain
_objc_release
_objc_retainAutoreleasedReturnValue
I checked, and these symbols are present in 5.0 but not 4.2:
iPhoneOS5.0.sdk/usr/lib $ find . -type f|xargs nm|grep -i _objc_retain$
00005ed0 T _objc_retain
000061d0 T _objc_retain
iPhoneOS4.2.sdk/usr/lib $ find . -type f|xargs nm|grep -i _objc_retain$
[... *crickets* ...]
Does this mean that Apple lied? I assume instead that I'm confused and doing something wrong, but I can't figure out what.
This is with the GM release of Xcode 4.2 (Build 4C199)
ARC is supported on iOS 4.3 and above. You need to use the iOS 5.x SDK but can select iOS 4.3 for the Deployment Target. The one thing that is not supported in 4.x is automatic weak reference zeroing.
See Apple's documentation here for the Objective-C Feature Availability Index.
Xcode 4.4 and 4.5 can be used to submit apps.
Note that NSDictionary and NSArray subscripting deploys back to OS X 10.6 and iOS 4, be sure to set the deployment target back as well.
A little bit late, but this is important information. The accepted answer is correct, Apple states iOS 4.0 and above as the minimum OS for ARC support.
However, it can break in a few situations. One of them is of course the __weak keyword and it's derivatives. You will see an error like the following.
dyld: lazy symbol binding failed: Symbol not found: _objc_initWeak
A second and very dangerous condition is when you use the +load method of NSObject. If you do this using ARC on iOS 4.x you will have runtime crashes that are very hard to find. If you get runtime errors like the following, check your +load methods. For me it worked to set the -fno-objc-arc flag for that particular file.
dyld: lazy symbol binding failed: Symbol not found: _objc_retainAutoreleasedReturnValue

XCode 3.2.3 running on iOS3 - Wired framework

I looked around on Stack Overflow and I didn't find the solution of a strange problem.
I started developing a project on XCode 3.1 then I decided to upgrade on XCode 3.2.4 and targeting iOS3 iPhones. I then followed the topics dealing with that and I changed the Base SDK to iOS 4.1 and the target os to 3.0. Everything worked fine until I made changes to my project.
Indeed I added CoreMedia.framework to my project.
It worked well on simulator, but crashed at launch on the iPhone. Here is the log I can get:
<Notice>: dyld: Library not loaded: /System/Library/Frameworks/CoreMedia.framework/CoreMedia
Referenced from: /var/mobile/Applications/72F009B5-82A8-49DC-A5CD-708EE1A4553C/myapp.app/myapp
Reason: image not found
(I had the same problem with other frameworks like CoreVideo for example)
I tried on an iOS4 iPhone and it worked well, so I think XCode doesn't link/copy the right framework on the iPhone. When I get info on a framework under XCode, here is the path I get:
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.1.sdk/System/Library/Frameworks/MediaPlayer.framework
But I get the same path when I get info on a framework of the first version of the project (when I was using XCode 3.1). It sounds like the new frameworks added have a wrong reference.
Does anybody have an idea of how to solve this problem? Any help would be greatly appreciated. :)
You have to weak link your libraries.
On xcode go to targets-> right click get info. on General tab on the lower section you will see your libs, change the CoreMedia type to be weak.
Ofcourse the lib won't be available on os3 so you'll need to add checks in your code so you wont call the lib on os3

IPhone SDK - CATextLayer Crash in < 3.2

I have created an app which runs fine on devices using iOS 3.2 or above but on older versions of the OS it crashes with the error
dyld: Symbol not found: _OBJC_CLASS_$_CATextLayer Referenced from: /var/mobile/Applications/70D5888B-B531-484F-997D-776B432FFA52/Test.app/Test Expected in: /System/Library/Frameworks/QuartzCore.framework/QuartzCore
I realize this is because CATextLayer wasn't available before 3.2 but does anyone know what I can do to still make it run in older versions? I have tried checking the version and only calling the layers if it's 3.2+ but the crash seems to happen when it loads in the framework instead of when it actually tries to change a layer.
Thanks.
weakly link the framework, then check to see if the class exists before using it in your code. There are multiple questions here on how to do that.
Follow the process that I describe in this answer, only weak link the QuartzCore framework in addition to UIKit. It's the same problem the asker was having there, only for a different symbol in a different framework.