7

考虑:

typedef void (^select_block_t)(UIView *) ;

(1) @property (copy, nonatomic) select_block_t        myBlockProperty ;
(2) @property (strong, nonatomic) select_block_t      myBlockProperty ;
(3) @property (assign, nonatomic) select_block_t      myBlockProperty ;

和:

(A) self.myBlockProperty = ^(UIView *) {NSLog(@"Hi");} ;
(B) self.myBlockProperty = [^(UIView *) {NSLog(@"Hi");} copy] ;

我试图了解将哪个属性声明与哪个块复制语义映射的正确方法是什么

我在这里看到了一些有利于[ 1:B]的例子

但是后来我对“复制”操作的冗余程度感到困惑。我有限的理解是 [1:A] 应该是正确的,因为我希望在分配属性时复制一次块,而不是在创建块时复制一次,然后在分配属性时再复制一次。

[3:B] 根据我的理由也是有意义的。那么,我误会了什么?

4

1 回答 1

9

[1:A] 是正确的,是的。[3:B] 不正确,因为:

  1. 不清楚该类是否拥有该属性,因此应该在 dealloc 中释放它(但应该)
  2. setter (B) 看起来像一个泄漏,静态分析器可能会这样标记它,因为块被复制,交给一个属性,然后离开范围,保留计数 +1。
  3. using (3) 意味着它仅在您设置保留计数为 1 的堆块(复制块)时才有效。这在使用该属性时为错误留下了很大的余地。(1) 适用于堆栈块和堆块,并且还将正确保留自动释放的块。

编辑:我看到你正在使用 ARC。在这种情况下,根本不可能使用 [3:B]。一旦超出范围,编译器将释放一个对象(即使是copyed),并且此属性设置器不会保留它。因此该属性将包含一个坏指针,它是一个等待发生的 EXC_BAD_ACCESS。

于 2012-04-09T17:43:18.543 回答