【问题标题】:iPhone check for a constant at runtime in universal appiPhone在通用应用程序运行时检查常量
【发布时间】:2011-02-13 04:13:45
【问题描述】:

我正在制作一个通用的 iPad/iPhone 应用程序,它可以使用 iPad 的 VGA 输出连接器将应用程序的内容镜像到外部屏幕上。但是,iPhone 没有此功能。给定以下代码,

#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(screenInfoNotificationReceieved:) 
          name:UIScreenDidConnectNotification
           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
         selector:@selector(screenInfoNotificationReceieved:) 
          name:UIScreenDidDisconnectNotification
           object:nil];
}
#endif

我在启动时在手机上收到此错误(在 ipad 中工作正常) “dyld:未找到符号:_UIScreenDidConnectNotification”

大概是因为 UIScreenDidConnectNotification 在 3.13 中还不存在。我如何在运行时检查这个?

更新添加了 ifdef 语句来检查 ipad 接口,但得到相同的结果!

UPDATED 添加了 NSLog 语句以确保 if 语句中的代码没有被调用。崩溃似乎发生在任何其他代码执行之前...

【问题讨论】:

  • 应用是在真 iPad 上运行还是在 iPad 模拟器中运行?
  • 应用程序在真正的 iPhone 上运行 - 当在 ipad sim 或真正的 ipad 中运行时,代码可以正常工作(如预期的那样)。

标签: iphone ipad universal


【解决方案1】:

按照http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html的“以编程方式确定设备”部分进行操作

#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 

在 cmets 部分。

【讨论】:

  • 这很奇怪,但这似乎不起作用。它适用于其他东西-(我在代码的其他部分使用 UI_USER_INTERFACE_IDIOM 来成功执行条件编译)但是当我在这里添加它时,我遇到了同样的问题,它仍然抱怨 UIScreenDidConnectNotification 没有被定义。在运行时 - 这不是编译器警告。
  • 仅供参考,我将您的代码段复制并粘贴到我的 3.2 项目中,并在模拟器中运行良好。奇怪...
  • 感谢 Horace 的测试,您的项目是否设置为通用应用程序?我的模拟器工作正常,因为它正在模拟 ipad:我在 3gs 上运行时遇到了这个问题 - ipad 工作正常......
  • 尝试将一些 NSLog 放入 #ifdef UI_USER_INTERFACE_IDIOM 以证明您已正确地从 iPhone 中排除了 3.2 代码 ;-)
  • 我在成语检查之后添加了 NSLog 语句,它没有被调用。看起来崩溃发生在启动时,在崩溃之前没有执行其他代码......
【解决方案2】:

试试弱链接 UIKit。添加到您的其他链接标志中:

-all_load -ObjC -weak_framework UIKit

如果你的目标是 3.1 之前的设备,但引用了一个只存在于 3.2 中的类,你不能用符号来引用它们,你必须使用 NSClassFromString。但在某些情况下这是不可能的,例如如果您将此类子类化(例如 UIPopoverController)。在这些情况下,您必须弱链接 UIKit。当你弱链接一个框架时,动态加载器会在启动时尝试解析所有符号,如果失败,它被设置为 NULL。

我猜常量 UIScreenDidConnectNotification 没有被标记(错误),所以你需要使用相同的解决方法。

弱链接有一个缺点。由于它必须在启动时执行此操作,因此动态地启动时间会受到影响。你必须测试它是否对你来说太慢了。

另一种弱链接框架的方法是:在您的目标上执行“获取信息”,然后在“常规”选项卡下,您将看到框架列表。将 UIKit 的类型更改为 Weak。

顺便说一句,使用 #ifdef 进行检查是行不通的,因为 #ifdef 是编译时构造,所以 UI_USER_INTERFACE_IDIOM 将始终被定义,因为您正在使用 3.2 SDK 进行构建

【讨论】:

  • 这行得通!我将该行添加到链接对话框中的“其他链接器标志”行中(这是正确的位置吗?)-您能告诉我这是在做什么以及为什么有效吗?它会影响应用程序中的其他任何内容吗?
  • 感谢您的澄清...在这种情况下,它似乎不会对启动时间造成太大影响-我同意-我认为这是一个错误(未标记 UIScreenDidConnectNotification)。
【解决方案3】:

另一种弱链接框架的方法是:在您的目标上执行“获取信息”,然后在“常规”选项卡下,您将看到框架列表。将 UIKit 的类型更改为 Weak。

这对我来说适用于运行时 iPhone 上的“找不到符号:_UIScreenDidConnectNotification”问题。

【讨论】:

    【解决方案4】:

    来自 Elfred 对相关问题的回答: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.
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多