3

I've compiled an app with IPhone base SDK 4.0, deployment target on iPhone OS 3.0. This app contains OS 4.0 new feature: local notification.

It works well on iPod 2G with OS 4.0; however it crashes every time the app start up on iPhone 1G with OS 3.0. It appears to be runtime reference error:

"dyld: Symbol not found: _OBJC_CLASS_$_UILocalNotification Referenced from: /var/mobile/Applications/73A3FAB1-63AE-4A71-8C6B-932142A728FE/Tapatalk X.app/Tapatalk X Expected in: /System/Library/Frameworks/UIKit.framework/UIKit"

If the UIKit framework is different between SDK3.0 & SDK4.0, why it doesn't report while compiling? How can I apply local notification feature on this app, while the app can still running on devices with OS3.0? Thanks.

user268743
  • 343
  • 1
  • 4
  • 14

3 Answers3

8

This answer solved the problem for me:

That error is being triggered because you didn't weak-link the UIKit framework. The UIKit framework in iPhone OS 3.2 added the UISplitViewController, and if you link it in as normal your application will assume those symbols exist on 3.0, where they don't.

To weak-link a framework, find your application target in Xcode, inspect it, and go to the General tab. At the bottom of that tab should be a list of frameworks, with a column for Type. Change the Type for UIKit from Required to Weak and rebuild your application. That should take care of the runtime errors.

This seems safe to me, given that UIKit is always going to be on the devices we're targetting.

Community
  • 1
  • 1
jamesh
  • 19,863
  • 14
  • 56
  • 96
  • 2
    Thanks for this solution! By the way, in XCode4, you do this by clicking on your top-level project folder, then clicking the 'Build Phases' tab. Then opening the 'Link Binary With Libraries' section. Then changing the setting for UIKit.framework from 'Required' to 'Optional' – Elijah Jul 16 '11 at 22:35
1

If you use a 4.0 SDK feature and you want to support 3.0 devices, you need to check that the functionality exists before you use it.

If you're using a new class (as you are) something like the following should work:

Class localNotificationC = NSClassFromString(@"UILocalNotification");
if (localNotificationC) {
    UILocalNotification* localNotification = [[localNotificationC alloc] init];

    // do stuff

    [localNotification release];
}
else {
    // what to do with the 3.0 SDK
}

As for why the compiler doesn't tell you, well, you told the compiler that you were using the 4.0 SDK and those classes/methods work on 4.0.

Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • This error can occur before any user code has been run. I have one class referencing UILocalNotification, correctly wrapping the code in a block as you suggested. The app crashes with the above error, long before it gets to that class/method. – jamesh Jul 05 '10 at 09:55
  • Thanks for your answer. But my question is the same as jamesh. This runtime reference error was happened while the app start up, not until the "UILocalNotification" be invoked. – user268743 Jul 05 '10 at 10:21
  • A framework that's new in iOS4 would certainly need to be weakly linked to your app. It wouldn't do any harm to do so against UIKit also, so it's certainly worth trying. I don't recall weak-linking against UIKit, though the "auto upgrade" to a Universal app may have done that for me. I'll check when I get back home. – Stephen Darlington Jul 05 '10 at 10:32
  • This is the correct answer. If you call any class methods of UILocalNotification, like 'alloc', you will get dynamic link errors before any of your code runs. If you acquire the class dynamically, as Stephen suggests, then you will by fine. Apple recommends this, and they certainly do *not* recommend weak-linking UIKit. – Darren Oct 27 '10 at 06:10
0

I found this information really useful. However my question is how to test if the application crashes or not after this change.

The background is I had the same issue with my iPad application. I have my BaseSDK set as 4.3 and Deployment target is 3.2. I never got this crash while doing ad-hoc provisioning and running the app on 3.2 iPad and it got approved by Apple too. But users reported that when they started the application after download on iPad 3.2 it crashes before showing the main screen even.

I was using [UILocalNotifition alloc] in my code which I think could be the result of below crash: Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x00000001, 0xe7ffdefe

I seem to have fixed this by converting the above statement as per Stephen's suggestion. However I really don't know how to test it. I am not getting any crash earlier too while testing the application before submission on 3.2 and currently also I am not getting any crash on start up.

I really need to validate this fix before I push the update to app store. Could someone please shed more light on how to test this? It would be really helpful if I can reproduce this crash with the previous version of my application and the same is not the case with current version after this fix.

indiantroy
  • 1,503
  • 1
  • 15
  • 25