Pet*_*isu 21 cocoa objective-c objective-c-blocks automatic-ref-counting
我用块做了好几次,就像我有强烈参考的指针一样
我听说你应该使用copy,但是使用块作为指针而不是原始对象的含义是什么?
我从来没有得到编译器的抱怨,我不应该使用
@property (nonatomic, strong) MyBlock block;
Run Code Online (Sandbox Code Playgroud)
但应该使用
@property (nonatomic, copy) MyBlock block;
Run Code Online (Sandbox Code Playgroud)
据我所知,块只是一个对象,所以为什么还要复制?
CRD*_*CRD 48
简答
答案是它是历史的,你是完全正确的,在当前的ARC代码中没有必要使用copy和strong属性是好的.例如,局部变量和全局变量也是如此.
答案很长
与其他对象不同,块可以存储在堆栈中,这是一种实现优化,因此与其他编译器优化一样,不应对编写的代码产生直接影响.这种优化有一个常见的情况,即创建一个块,作为方法/函数参数传递,由该函数使用,然后丢弃 - 可以在堆栈上快速分配块,然后在没有堆的情况下处理(动态内存池)参与其中.
将此与局部变量进行比较,其中(a)在堆栈上创建,(b)在拥有函数/方法返回时自动销毁,(c)可以通过地址传递给拥有函数调用的方法/函数.在其拥有的函数/方法返回后,无法存储和使用局部变量的地址- 该变量不再存在.
但是,期望对象比它们的创建函数/方法(如果需要)更长,因此与局部变量不同,它们在堆上分配,并且不会根据它们的创建函数/方法返回而自动销毁,而是基于它们是否仍然需要 - 以及这里的"需要"由ARC自动确定.
在堆栈上创建一个块可能会优化一个常见的情况,但它也会导致一个问题 - 如果块需要像对象那样经常使用它的创建者,那么它必须在它的创建者堆栈被销毁之前移动到堆.
当块实现首次发布时,程序员可以看到堆栈上存储块的优化,因为当时编译器无法在需要时自动处理将块移动到堆 - 程序员必须使用函数block_copy()自己完成.
虽然这种方法在低级C世界中可能不是不合适的(并且块是C构造),但让高级Objective-C程序员手动管理编译器优化实际上并不好.随着Apple发布了更新版本的编译器改进.在早期它的程序员们被告知,他们可以代替block_copy(block)用[block copy],与正常Objective-C对象配合英寸 然后编译器开始根据需要自动从块中复制块,但这并不总是正式记录.
虽然苹果公司不能摆脱它的起源并且将这样做称为"最佳实践" - 这当然是有争议的,但是没有必要在一段时间内从堆栈中手动复制块.在Apple的Working with Blocks的最新版本2014年9月,他们表示应该使用块值属性copy,但随后立即清理(强调添加):
注意:您应该将copy指定为属性属性,因为需要复制块以跟踪其在原始范围之外的捕获状态.在使用自动引用计数时,您不必担心这一点,因为它会自动发生,但属性属性的最佳做法是显示结果行为.
没有必要"显示结果行为" - 首先将块存储在堆栈上是一种优化,并且应该对代码透明 - 就像其他编译器优化一样,代码应该在没有程序员参与的情况下获得性能优势.
因此,只要您使用ARC和当前的Clang编译器,您就可以像其他对象一样处理块,并且因为块是不可变的,这意味着您不需要复制它们.信任Apple,即使他们似乎怀念"我们手工做事的好时光"并鼓励您在代码中留下历史提醒,copy也不需要.
你的直觉是正确的.
HTH
| 归档时间: |
|
| 查看次数: |
6771 次 |
| 最近记录: |