1. 程式人生 > >iOS為什麼Block的屬性宣告要用copy

iOS為什麼Block的屬性宣告要用copy

在實際開發中,發現使用Block有著比delegate和notification更簡潔的優勢。於是在目前的專案中大量的使用block。

  在我的標頭檔案我是這樣宣告使用block的。

  1. @interface BrushViewController : BaseViewController  
  2. @property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);  
  3. @end  

我將block宣告為copy的原因是在程式碼塊裡面我可能會使用一些本地變數。而block一開始是放在棧上的,只有copy後才會放到堆上。

如果加copy屬性,當其所在棧被釋放的時候,這些本地變數將變得不可訪問。一旦程式碼執行到block這段就會導致bad access。

  1. brush.getCardInfo=^(NSDictionary *info){  
  2.     [self test];  
  3. };  
像上面這段程式碼,self其實是一個本地變數而不是block內部變數,如果宣告為assign,程式碼執行到block內部就會出錯。

但是這又帶來另一個問題,就是self的引用計數+1。這意味著很可能會導致迴圈引用。self持有brush,brush持有block,block持有self。結果就是記憶體洩漏。

解決的辦法如下:

  1. __block CurrentViewController* blockSelf = self;  
  2. brush.getCardInfo=^(NSDictionary *info){  
  3.         [blockSelf test];  
  4. };  

通過這個方式,告訴block這個變數的引用計數不要+1。

如果你使用的是ARC,那麼就應該改成下面這樣:

  1. __weak CurrentViewController* blockSelf = self;  
  2. brush.getCardInfo=^(NSDictionary *info){  
  3.         [blockSelf test];  
  4. };