由于UIPopoverController,通用iOS应用程序在iPhone / iTouch 3.1.3上崩溃

我刚刚更新了我的应用程序,因此它是一个通用应用程序。 这样做我在某个地方添加了对UIPopoverController支持。 现在该应用程序似乎在3.1.3 iPhone / iTouch设备上崩溃:

 OS Version: iPhone OS 3.1.3 (7E18) Report Version: 104 Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x00000001, 0xe7ffdefe Crashed Thread: 0 Dyld Error Message: Symbol not found: _OBJC_CLASS_$_UIPopoverController 

我没有得到的是,如果硬件是iPad,我只会尝试调用UIPopoverController:

 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:btc]; CGSize popoverSize = { 300.0, 500.0 }; popover.delegate = self; popover.popoverContentSize = popoverSize; self.bmPopover = popover; [popover release]; [self.bmPopover presentPopoverFromBarButtonItem:self.bmBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } else { [self presentModalViewController:nav animated:YES]; } 

我确实有一个iVar和一个UIPopoverController类型的属性声明但我不希望这会在运行时导致问题,如果我实际上没有尝试调用类中的方法。

我不应该做什么来确保系统在运行时不会尝试与UIPopoverController链接?

对于通用应用程序,您不仅应检查这是否是ipad或此类是否存在,而且您应将UIKit链接为弱引用而非默认(强),为此:

  1. 获得目标信息
  2. 选择一般
  3. 在链接库中更改UIKit所需的UIKit弱

制作通用应用程序很有趣:]

尽管此代码很可能永远不会在iPhone上运行,但它仍然会被链接,因此您收到错误。 在实例化之前,您需要检查该类是否存在。 您可以将上面的代码修改为以下代码来修复它。

 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { Class UIPopoverControllerClass = NSClassFromString(@"UIPopoverController"); if (UIPopoverControllerClass != nil) { UIPopoverController *popover = [[UIPopoverControllerClass alloc] initWithContentViewController:btc]; CGSize popoverSize = { 300.0, 500.0 }; popover.delegate = self; popover.popoverContentSize = popoverSize; self.bmPopover = popover; [popover release]; [self.bmPopover presentPopoverFromBarButtonItem:self.bmBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } } else { [self presentModalViewController:nav animated:YES]; } 

此外,您可能会弱化与UIKit框架的链接,这也可以解决问题。 我更喜欢代码解决方案,因为它更安全。

您需要通过从字符串引用类来停止编译器错误。 这应该与UI_USER_INTERFACE_IDIOM()一起使用,并将在不知道UIPopoverController的SDK上编译。 这是一个例子:

 Class popClass = NSClassFromString(@"UIPopoverController"); if(popClass) { id infoPop = [[popClass alloc] initWithContentViewController:popViewController]; [infoPop presentPopoverFromRect:CGRectMake(20, 70, 10, 10) inView:self.view permittedArrowDirections:4 animated:YES]; } 

答案很简单:

在Xcode项目中,选择顶级项目图标。 执行获取信息 ,转到“编辑”面板。 将配置设置所有配置 ,将显示:设置为**所有设置**

iOS部署目标设置为iOS 3.1。

重新编译。 您的程序失败,因为最小操作系统设置得太高,因此加载程序无法解析符号UIPopoverController 。 我刚刚走过的这个改变使得这个符号很弱:它将解析为NULL,但至少你的程序会加载。


您是否正在加载隐式创建UIPopoverController的NIB文件? 这是另一种崩溃的方式。

我发现添加它很有用,这样我就可以在3.2之前的系统上使用UI_USER_INTERFACE_IDIOM()。

 #ifndef __IPHONE_3_2 // if iPhoneOS is 3.2 or greater then __IPHONE_3_2 will be defined typedef enum { UIUserInterfaceIdiomPhone, // iPhone and iPod touch style UI UIUserInterfaceIdiomPad, // iPad style UI } UIUserInterfaceIdiom; #define UI_USER_INTERFACE_IDIOM() UIUserInterfaceIdiomPhone #endif // ifndef __IPHONE_3_2