还有其他人在使用 XCode 4.2(lion) 或 4.0.2 中的 4.3 iPhone 模拟器时遇到问题吗?
我的代码长期有效、经过测试并且在生产中使用 block 来指定完成操作。例如,我使用 UIView 动画淡出标签顶部的一些文本,如下所示:
[UIView animateWithDuration: 0.0
delay: 0.0
options: (UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionNone)
animations: ^{
videoTextLabel1.alpha = 0.0;
videoTextLabel2.alpha = 0.0;
videoTextLabel3.alpha = 0.0;
}
completion: ^(BOOL completed) {
[self fadeInNextMeditationLine: 0];
}];
我在模拟器中可靠地获得了 EXEC_BAD_ACCESS - 在设备上从来没有问题。
在另一个地方,我使用自己的完成 block 实现在用户关闭模态视图后采取行动。
ValuePickerController *controller =
[[ValuePickerController alloc]
initWithNibName: kValuePickerXIBFileName
bundle: nil
labelText: @"prompt")
value: alertSettings.frequency
minimumValue: kMinimumFrequency
maximumValue: kMaximumFrequency
completionBlock: ^(NSInteger newValue) {
[self updateFrequencyText: newValue];
[self changeFrequencySetting];
}];
没有 NSZombies 出现,分析器运行干净。此外,此代码已投入生产 6 个月,没有发生任何崩溃。
还有其他人遇到这个问题吗?自从我升级 XCode 以来,它一直在发生。
最佳答案
据我所知,这是一个只影响 4.3 模拟器的已知问题。 4.2 和预发布的 5.0 版本似乎没有出现这个问题。然而,现在 Lion 已经出局,这是一个更大的问题,因为 Xcode 的最新通用发行版仅支持 4.3 模拟器,因此会出现此问题。
真正的原因在于 Blocks 和 ObjC 运行时之间的钩子(Hook)。 block 本身会工作得很好,但任何尝试在它们上调用 Objective-C 消息都会导致段错误。这是因为 Blocks 运行时包含一些对相关 ObjC 类的未初始化引用,并且在 iOS 4.3 模拟器上,这些在 ObjC 运行时加载时从未被初始化(它们仅在 ObjC 被使用时才被初始化——所以Blocks 运行时不依赖于加载 Foundation)。您可以在运行时通过在调试器中查看 _NSConcreteStackBlock
、_NSConcreteGlobalBlock
和 _NSConcreteMallocBlock
的值来检查这一点。在 4.2 模拟器或设备上,这些值将不为零,但在 4.3 模拟器上它们仍然为零。
我有一个可能的解决方案,如有必要,我会链接到这里,但首先我会尝试从 Apple 那里获取一些信息,了解他们是否已在发布的风口浪尖上进行修复,或者他们是否需要更多信息信息等
更新:问题已解决
我进行了大量挖掘,最终归结为:不要使用 -weak_library
对 libSystem.dylib 进行弱链接。相反,您根本不应该弱链接 libSystem(我在支持 iOS 3.1.x 时必须这样做,因为编译器在某些特定于 iOS4 的条件代码中生成的 Blocks 代码在启动时导致链接错误,即严重崩溃),或者您应该改用 -weak lSystem
,模拟器可以更好地理解它。
当您在 iOS 模拟器中运行时,您可以查看加载的库(在 Xcode 中:'Product->Debug->Shared Libraries…'),如果您搜索“Blocks”,您将看到两个项目: libsystem_blocks.dylib
和 libsystem_sim_blocks.dylib
。后者是由 CoreFoundation 链接的,它为 Blocks 运行时初始化 ObjC 运行时胶水。但是,由于您将 libSystem
库作为一个整体进行弱链接,因此通常被模拟器版本覆盖的符号(因为它加载晚于 libSystem)实际上在运行时从 第一个 实现它们的库。这意味着您会找到 _NSConcreteGlobalBlock
和 friend 的系统版本,它们不是由模拟器的自定义 ObjC 运行时初始化的版本。
有关该问题的(很多!)更多信息,并查看我是如何追踪到它的,请查看我创建的线程 on the Apple Developer Forums .
关于objective-c - 在 iPhone Simulator 4.3/XCode 4.2 和 4.0.2 中使用 Blocks 会导致应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6738858/