由于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链接为弱引用而非默认(强),为此:
- 获得目标信息
- 选择一般
- 在链接库中更改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