應當使用:@property (nonatomic, copy)
今天在這個問題上犯錯誤了,找了好久才知道原因。
另外,簡單的進行反組譯碼看了下,Block 被儲存在靜態變數區,運行時構造出一個運行棧,進行調用。
retain 並不會改變 Block 的引用計數,因此對 Block 應用 retain 相當於 assign。
但是既然在靜態儲存區,為什麼會出現 EXC_BAD_ACCESS 呢?代碼都在的呀。
網上都說 Block 在棧上,這應該是錯誤的:指向 Block 代碼的指標在棧上。
我感覺原因是這樣:
執行靜態區的代碼,需要特殊的構造,比如:載入到寄存器,調整好 ESP 等。
而堆上的代碼可以直接執行。
期待更詳細的解釋。
When storing blocks in properties, arrays or other data structures, there’s an important difference between using copy
or retain
. And in short, you should always use copy
.
When blocks are first created, they are allocated on the stack. If the block is called when that stack frame has disappeared, it can have disastrous consequences, usually a EXC_BAD_ACCESS or something plain weird.
If you retain
a stack allocated block (as they all start out being), nothing happens. It continues to be stack allocated and will crash your app when called. However, if you copy
a stack allocated block, it will copy it to the heap, retaining references to local and instance variables used in the block, and calling it will behave as expected. However, if you copy
a heap allocated block, it doesn’t copy it again, it just retains
it.
So you should always declare your blocks as properties like this:
@property (copy, ...) (int)(^aBlock)();
And never like this:
@property (retain, ...) (int)(^aBlock)();
And when providing blocks to NSMutableArray
s and the like, always copy
, never retain
.