天天看點

【iOS7的一些總結】14、Block的概念和應用

我們知道,不同對象之間通信的方法比較常用的有代理(delegate)、通知中心(NotificationCenter)等方法。Block則是另一種對象間通信的方法。其中,delegate和block相關的兩個對象是一對一的關系,通知中心所反映的則是一對多的關系,通過這些方法實作了對象間的解耦合(功能相關,但沒有繼承與派生關系)。

1、簡介

Block在ios 4.0之後加入,并大量使用在新的ios api中。block是一個匿名的代碼塊,可以作為傳遞給其他對象的參數,并得到傳回值。從本質上講,block同其他普通的變量類似,隻是其儲存的資料是一個函數體。Block不隻是針對Objective-C的專利,而是一種可以應用于C、C++和OBjective-C的語言層面的新特性。通過使用block,開發者可以将一段代碼段像某一個數值一樣當做參數傳遞給函數。同時,blocks也是Objective-C的一種對象,可以像其他對象一樣添加到NSArray或者NSDictionary等集合中。

2、使用方法

(1)聲明一個block:

(2)建立一個block:

(3)調用block:

熟悉C/C++的TX也許有一種感覺,即ios的block機制十分類似前者的函數指針這一概念。

(4)聲明block的類型:利用typedef簡化block的定義和實作,尤其是對同一種格式定義多個block時更加明顯。

3、block作為函數的參數:

通過将block作為函數的參數進行傳遞,可以實作類似回調函數的功能;

.....

4、Block中的變量

Block中可以使用全局變量和局部變量,對二者的處理有所不同。block引用局部變量時,将該變量作為常量編碼到代碼塊中;如果想在block中進行修改,則必須使用__block進行修飾。如:

5、Block的記憶體管理

對于在block内部引用的對象,__block也是關鍵因素。如果在block内部引用了一個局部對象,那麼該對象的引用計數會+1;除非該對象由__block修飾,那麼其引用計數不變。這麼做的主要原因是block的代碼經常涉及到延遲執行的情況,是以ios将block内部涉及到的對象進行retain,防止在block中的代碼執行之前該對象就被釋放掉。

對block的記憶體管理通常可以使用copy和release方法。在建立之初,block的記憶體配置設定在棧中,copy之後轉移到堆中。

避免在實作block時發生對self的強循環引用:

簡而言之,如果一個類包含一個block作為property,那麼這個block的copy屬性可以認為是self對block的強引用,而一個block對其内部調用的變量和對象同樣存在強引用關系。那麼如果一個block在實作時調用了self的方法,那麼将會造成self和block的強循環引用,使得記憶體無法被釋放。為了避免這種情況,在block内部調用self的時候,需要重新定義一個由__weak修飾的self副本,并以該副本調用self的方法,如下代碼所示: