【问题标题】:Use of Blocks crashes app in iPhone Simulator 4.3/XCode 4.2 and 4.0.2在 iPhone Simulator 4.3/XCode 4.2 和 4.0.2 中使用 Blocks 会导致应用崩溃
【发布时间】:2011-07-18 20:15:18
【问题描述】:

还有其他人在使用 XCode 4.2(lion) 或 4.0.2 中的 4.3 iPhone 模拟器时遇到问题吗?

我的代码长期以来一直在工作、测试和生产中使用块来指定完成操作。例如,我使用 UIView animate 来淡出标签顶部的一些文本,如下所示:

[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 后就一直在发生这种情况。

【问题讨论】:

  • 更新——我在另一个代码领域发现了这个问题,共同点似乎是我使用块来指定以后会发生什么。我创建了一个类似的函数,它在模式视图中请求一个值,然后在选择值后执行 2 个方法:
  • 我有同样的问题,没有解决办法。糟透了。

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


【解决方案1】:

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

真正的原因在于 Blocks 和 ObjC 运行时之间的钩子。块本身可以正常工作,但任何尝试在其上调用 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 时必须这样做,因为编译器生成的 Blocks 代码在某些特定于 iOS4 的条件代码中会在启动时导致链接错误,即严重的崩溃),或者您应该改用-weak lSystem,模拟器更容易理解。

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

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

【讨论】:

  • 您是否从 Apple 那里听到过这方面的消息?这样一个令人沮丧的问题,特别是如果您使用的是较新版本的 Xcode,您甚至无法访问以前的模拟器版本来解决此问题。
  • 我在最新的模拟器上也得到了这个,即使这些对象不是 NIL。
  • 以防万一没有人收到关于我上面编辑的通知:我解决了它,这是一个简单的修复。我的答案已经过编辑以包含详细信息。
  • 感谢您的挖掘,这已经困扰了我们一段时间,现在变得必不可少,因为最新版本的 Xcode 没有 4.3 模拟器,这也破坏了 5.0 模拟器。简单来说,需要做的是: 1. 在项目 Build Settings 编辑器中,在标题“Linking”下,查找“Other Linker Flags”。 2. 将有-weak_library-all_load-ObjC 的条目。 3. 单击-weak_library 的条目并将其替换-weak-lSystem。 4. 瞧!
  • 值得一提的是,Apache Cordova 1.7(又名 Phonegap)在其模板生成的项目中存在这个问题。我已经和他们一起记录了一个错误报告 (issues.apache.org/jira/browse/CB-754)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多