开发者

iPhone check for a constant at runtime in universal app

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜