I'm making a universal iPad/iPhone app which can use the iPad's VGA out connector to mirror the content of the app on an external screen. However, the iPhone does not have this functionality. given the following code,
#ifdef UI_USER_INTERFACE_IDIOM
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
NSLog(@"this code should not execute on iphone");
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scre开发者_StackOverflow社区enInfoNotificationReceieved:)
name:UIScreenDidConnectNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(screenInfoNotificationReceieved:)
name:UIScreenDidDisconnectNotification
object:nil];
}
#endif
I get this error on the phone at launch (works fine in ipad) "dyld: Symbol not found: _UIScreenDidConnectNotification"
presumably because UIScreenDidConnectNotification doesnt' exist yet in 3.13. How do I check for this at runtime?
UPDATED added ifdef statements to check for ipad interface but getting the same result!
UPDATED added NSLog statement to make sure the code inside the if statement is not being called. The crash seems to occur before any other code is executed...
Try weak link UIKit. Add into your other link flags:
-all_load -ObjC -weak_framework UIKit
If you target pre-3.1 devices but refer to a class which only exists in 3.2, you can't refer to them by symbol, you have to use NSClassFromString. But there are cases where this isn't possible, e.g. if you subclass such a class (say UIPopoverController). In those cases you have to weak-link UIKit. When you weak-link a framework, the dynamic loader attempts to resolve all the symbols on startup, if it fails, it's set to NULL.
I'm guessing the constant UIScreenDidConnectNotification isn't tagged (bug), so you need to use the same workaround.
There is a downside to weak-linking. Since it has to do this upon startup, dynamically, startup time takes a hit. You'll have to test if it is too slow for you.
Another way to weak link a frame is: do "Get Info" on your target and under the General tab, you will see the list of frameworks. Change the type for UIKit to Weak.
BTW, using a #ifdef to check doesn't work, because #ifdef are compile-time constructs, so UI_USER_INTERFACE_IDIOM will always be defined because you are building using the 3.2 SDK
From Elfred's answer to related question: How to test for the existance of a constant when creating a iPhone universal binary
if (NULL != &UIBackgroundTaskInvalid) {
//do multitasking stuff here
} else {
// don't do multitasking stuff here.
}
Follow the "Programmatically Determining Device" section at http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html
plus
#ifndef __IPHONE_3_2 // if iPhoneOS is 3.2 or greater then __IPHONE_3_2 will be defined
typedef enum { // provided by noblemaster ]:-|
UIUserInterfaceIdiomPhone, // iPhone and iPod touch style UI
UIUserInterfaceIdiomPad, // iPad style UI
} UIUserInterfaceIdiom;
#define UI_USER_INTERFACE_IDIOM() (([[UIDevice currentDevice].model rangeOfString:@"iPad"].location != NSNotFound) ? UIUserInterfaceIdiomPad : UIUserInterfaceIdiomPhone)
#endif // ifndef __IPHONE_3_2
in the comments section.
Another way to weak link a frame is: do "Get Info" on your target and under the General tab, you will see the list of frameworks. Change the type for UIKit to Weak.
That worked for me for the issue "Symbol not found: _UIScreenDidConnectNotification" on iPhone at runtime.
精彩评论