【问题标题】:Under ARC, are Blocks automatically copied when assigned to an ivar directly?在 ARC 下,直接分配给 ivar 时会自动复制块吗?
【发布时间】:2012-05-04 17:11:36
【问题描述】:

假设ARC下的代码如下,

typedef void (^MyResponseHandler) (NSError *error);
@interface MyClass : NSObject
{
    MyResponseHandler _ivarResponseHandler;
}

- (void)myMethod:(MyResponseHandler)responseHandler
{
    _ivarResponseHandler = responseHandler;
    ...
}

问题:block 分配给 ivar 时是否会自动复制到堆中?

My previous question 暗示它在通过@property 分配时被复制。但是,今天我使用上面的代码并收到了一个EXC_BAD_ACCESS,通过更改为

_ivarResponseHandler = [responseHandler copy].

【问题讨论】:

    标签: objective-c automatic-ref-counting objective-c-blocks ivar


    【解决方案1】:

    编辑:我之前的回答可能是错误的。

    ARC docs 中的一些节选说:

    3.可保留对象指针

    可保留对象指针(或可保留指针)是可保留对象指针类型(可保留类型)的值。可保留对象指针类型共有三种:

    • 块指针(通过将插入符号 (^) 声明符符号应用于函数类型而形成)

    4.2.语义

    在评估赋值运算符时会发生赋值。语义因限定而异:

    • 对于 __strong 对象,首先保留新的指针;其次,左值加载了原始语义;第三,新的指针对象以原始语义存储到左值中;最后,旧指针被释放。这不是原子执行的;面对并发加载和存储时,必须使用外部同步来确保安全。

    4.4.1。对象

    如果一个对象声明为具有可保留对象所有者类型,但没有明确的所有权限定符,则其类型被隐式调整为具有 __strong 限定符。

    7.5。块

    除了作为初始化 __strong 参数变量或读取 __weak 变量的一部分完成的保留之外,每当这些语义要求保留块指针类型的值时,它具有 Block_copy 的效果。当优化器发现结果仅用作调用的参数时,它可能会删除此类副本。

    所以我认为答案是可能,具体取决于优化器。

    【讨论】:

    • 您知道我是在询问自动引用计数环境吗?看来您的 foo/bar 示例在 ARC 中不会有问题...?
    • 是的,对不起。您的回答或提供的苹果文档没有说明 ARC 在分配给实例变量时是否会自动将块移动到堆中。看来这个问题的答案必须来自clang Objective-C Automatic Reference Counting documentation
    • 感谢所有的努力。哇,这个文档太难理解了。实际上,我会读到编译器会插入一个 Block_copy。似乎 ivar 默认为 __strong,因此分配将“要求保留块指针类型的值”,从而插入 Block_copy。认为有一个明确的答案会很棒,我想现在我会满足于将块存储在 @property(copy) 中。
    【解决方案2】:

    您的问题和解决方案表明我对您其他问题的回答可能是错误的。我基于the clang Objective-C Automatic Reference Counting documentation第7.5节的最后一段:

    除了作为初始化__strong参数变量或读取__weak变量的一部分完成的保留之外,每当这些语义要求保留块指针类型的值时,它具有Block_copy的效果.当优化器发现结果仅用作调用的参数时,它可能会删除此类副本。

    我认为“这些语义”是指整个文档,但如果“这些语义”仅指第 7.5 节,那么 ARC 只会为被块捕获的块插入 Block_copy

    【讨论】:

    • 我同意不清楚“这些语义”指的是什么
    • 我与编写此部分的 Apple 工程师进行了交谈。他说“这些语义”是指整个文档。因此应该自动插入Block_copy。似乎这可能是早期的一个错误,后来被修复了。
    猜你喜欢
    • 2012-05-12
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    相关资源
    最近更新 更多