微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

objective-c-blocks和ARC – 发布版本的复制或崩溃(由优化级引起)

我正在使用 Xcode 4.3.3并开发iOS 5.0.在开发ARC iOS应用程序时,我已经开始使用块作为异步操作的回调机制.该应用程序在模拟器和设备上正常工作.

然后我第一次运行该分析器,并且它几乎马上就开始崩溃 – 特别是在尝试调用一个回调块时,EXC_BAD_ACCESS.

经过一番调查,很明显,行为的差异是因为在认情况下,分析器运行在“发布模式” – 特别是优化级别设置为“最快,最小[-Os]”而不是“无[-O0] ”.

例如,以下代码(针对此问题简化)将在尝试执行callbackBlock时崩溃:

- (void) setCallbackBlock:(void (^)(Nsstring *input))block
{
    callbackBlock = block;
}

- (void) invokeCallbackWithInput:(Nsstring *)input
{
    if (callbackBlock) {
        callbackBlock(input);
    }
}

调试到它,调用setCallbackBlock,优化级别设置为“None”,传入的块将是一个NsstackBlock,并且callbackBlock将成为一个NSMallocBlock.

然而,优化级别“最快,最小”,仍然是NsstackBlock.

更改setter代码以使用[block copy]来修复崩溃问题(基于iOS 5 blocks crash only with Release Build).

然而,另一个相关的问题表明,ARC-Why does Objective-C block still work without copying it to the heap?中的ARC – 块变量被复制到堆中不是必需的

所以我的问题:这里发生了什么,为什么? (另外,这两个答案如何正确??)

编辑:
要澄清如何声明callbackBlock – 就在我的@implementation之上,那些方法是这样的:

@interface MyClass ()
{
    void (^callbackBlock)(Nsstring *input);
}

@end

解决方法

So my question: What’s going on here,and why? (Also,how can both of those answers be correct…?)

我实际上认为the other question的答案是错误的,因为它没有回答关于ARC中的块的特定问题.问题是将一个基于堆栈的块从一个函数/方法传递给另一个.答案是一些不同的东西,这是捕获一个块内的__block变量.这是一个不同的问题.

您的问题的答案是Transitioning to ARC Release Notes:的常见问题

Blocks “just work” when you pass blocks up the stack in ARC mode,such as in a return. You don’t have to call Block copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain.

所以这样做的方式是,当你传递一个块(在你的情况下是在堆栈上分配的块文字)时,编译器在初始化该调用的参数时不会复制该块.被调用函数方法有责任在需要时复制该块本身.

当ARC从函数方法返回块时,ARC自动复制块.在这种情况下,编译器知道它必须为你做一个复制到堆,所以它.

所以你的设置者应该做一个块拷贝,甚至用ARC.

我希望有帮助.

原文地址:https://www.jb51.cc/c/111823.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐