使用Blocks会在iPhone模拟器4.3 / XCode 4.2和4.0.2中崩溃应用程序

时间:2011-07-18 20:15:19

标签: objective-c ios xcode ios-simulator objective-c-blocks

其他人在XCode 4.2(Lion)或4.0.2中遇到4.3 iPhone模拟器的问题?

我的代码长期以来一直在工作,测试和生产中使用块来指定完成操作。例如,我使用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 - 从不会在设备上出现问题。

在另一个地方,我使用自己的完成块实现在用户取消模态视图后采取行动。

    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以来,它一直在发生。

1 个答案:

答案 0 :(得分:22)

据我所知,这是一个已知问题,只影响4.3模拟器。 4.2和预发行版5.0版本似乎没有出现此问题。然而,Lion现在出了问题,因为Xcode的最新通用版本只支持4.3模拟器,而这个问题就出现了。

实际原因是Block和ObjC运行时之间的钩子。块本身也可以正常工作,但任何在它们上调用Objective-C消息的尝试都会导致段错误。这是因为Blocks运行时包含对相关ObjC类的几个未初始化的引用,并且在iOS 4.3模拟器上,当ObjC运行时加载时它们从未被初始化(它们仅在ObjC被使用时才被初始化 - 所以Blocks运行时不依赖于加载Foundation。您可以在运行时通过查看调试器中_NSConcreteStackBlock_NSConcreteGlobalBlock_NSConcreteMallocBlock的值来检查此问题。在4.2模拟器或设备上,这些值将是非零的,但在4.3模拟器上它们仍为零。

我有一个潜在的解决方案,如果有必要,我会链接到这里,但首先我要尝试&从苹果公司那里获取一些信息,告诉他们是否已经解决了发布的问题,或者他们是否需要更多信息等等。

更新:问题已解决

我做了很多挖掘,最终归结为:不使用-weak_library 对libSystem.dylib进行弱连接。相反,你应该根本不弱连接libSystem(我不得不支持iOS 3.1.x,因为在某些特定于iOS4的条件代码中编译器生成的Blocks代码在启动时导致链接错误,即坏的崩溃),或者你应该使用-weak lSystem代替,模拟器可以更好地理解。

当您在iOS模拟器中运行时,您可以查看加载的库(在Xcode:'Product-&gt; Debug-&gt; Shared Libraries ...'),如果您搜索'Blocks',您会看到两个项目:libsystem_blocks.dyliblibsystem_sim_blocks.dylib。后者是由CoreFoundation链接的,它为Blocks运行时初始化ObjC运行时粘合剂。但是,由于您将libSystem库作为一个整体进行弱链接,因此通常由Simulator版本覆盖的符号(因为它比libSystem更晚加载)实际上是在运行时从第一个< / em>实现它们的库。这意味着您将找到_NSConcreteGlobalBlock和朋友的系统版本,这些版本不是由Simulator的自定义ObjC运行时初始化的版本。

对于(很多!)有关问题的更多信息,以及查看我如何跟踪它,请查看我创建的主题on the Apple Developer Forums