天天看點

iOS開發-Block回調

簡單的Block寫法,傳回類型  Block名稱  參數,基本上符合方法的寫法,先看一個最簡單的Block寫法:

1

2

3

4

5

<code>int</code>  <code>(^blockDemo)(</code><code>int</code> <code>a,</code><code>int</code> <code>b)=^(</code><code>int</code> <code>a,</code><code>int</code> <code>b){</code>

<code>    </code><code>return</code> <code>a+b;</code>

<code>};</code>

<code>NSLog</code><code>(@</code><code>"BlockDemo的結果:%d"</code><code>,blockDemo(90,72));</code>

最後的結果是162,簡單明了,很容易看懂,現在我們先通過UITableView展示背景資料,效果如下:

iOS開發-Block回調

ViewController中的代碼,簡單的實作了一下UITableView:

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<code>- (UITableView *)tableView {</code>

<code>    </code><code>if</code> <code>(!_tableView) {</code>

<code>        </code><code>_tableView = [[UITableView alloc]</code>

<code>                      </code><code>initWithFrame:CGRectMake(0, 64, CGRectGetWidth(</code><code>self</code><code>.view.bounds) - 10,</code>

<code>                                               </code><code>CGRectGetHeight(</code><code>self</code><code>.view.bounds) - 64)</code>

<code>                      </code><code>style:UITableViewStylePlain];</code>

<code>        </code><code>_tableView.rowHeight = 40.0;</code>

<code>        </code><code>_tableView.sectionHeaderHeight = 0.0;</code>

<code>        </code><code>_tableView.sectionFooterHeight = 0.0;</code>

<code>        </code><code>_tableView.dataSource = </code><code>self</code><code>;</code>

<code>        </code><code>_tableView.delegate = </code><code>self</code><code>;</code>

<code>    </code><code>}</code>

<code>    </code><code>return</code> <code>_tableView;</code>

<code>}</code>

<code>-(</code><code>NSInteger</code><code>)tableView:(UITableView *)tableView numberOfRowsInSection:(</code><code>NSInteger</code><code>)section{</code>

<code>    </code><code>return</code> <code>[</code><code>self</code><code>.dataSource count];</code>

<code>-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(</code><code>NSIndexPath</code> <code>*)indexPath{</code>

<code>    </code><code>UITableViewCell  *cell=[[UITableViewCell alloc]init];</code>

<code>    </code><code>cell.textLabel.text=[</code><code>self</code><code>.dataSource objectAtIndex:indexPath.row];</code>

<code>    </code><code>return</code> <code>cell;</code>

通過FEDataService中的fetchData取出資料:

<code>-(</code><code>NSMutableArray</code> <code>*)fetchData{</code>

<code>    </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"部落格園"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技術交流群:228407086"</code><code>,</code><code>nil</code><code>];</code>

<code>    </code><code>return</code> <code>mutableArray;</code>

Controller中的調用:

<code>self</code><code>.dataService=[[FEDataService alloc]init];</code>

<code>self</code><code>.dataSource=[</code><code>self</code><code>.dataService  fetchData];</code>

當時從背景取資料是需要時間的,而且網絡不一定能取出資料,這個時候就可以通過Block進行回調,在DataService中重新定義了一個fetchDataSource方法:

<code>-(</code><code>void</code><code>)fetchDataSource:(</code><code>void</code><code>(^)(</code><code>NSMutableArray</code> <code>*array,</code><code>NSError</code> <code>*error))fetchDataBlock;</code>

注意這裡的Block傳參的寫法,fetchDataBlock相當于是參數名,前面的是類型,實作中加入了GCD

<code>-(</code><code>void</code><code>)fetchDataSource:(</code><code>void</code> <code>(^)(</code><code>NSMutableArray</code> <code>*, </code><code>NSError</code> <code>*))fetchDataBlock{</code>

<code>    </code><code>dispatch_time_t  time=dispatch_time(DISPATCH_TIME_NOW, </code><code>NSEC_PER_SEC</code><code>*(int64_t)1.0);</code>

<code>    </code><code>dispatch_after(time,dispatch_get_main_queue() , ^{</code>

<code>         </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"部落格園"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技術交流群:228407086"</code><code>,</code><code>nil</code><code>];</code>

<code>        </code><code>fetchDataBlock(mutableArray,</code><code>nil</code><code>);</code>

<code>    </code><code>});</code>

<code>    </code> 

Controller中進行回調同樣實作以上效果:

<code>[</code><code>self</code><code>.dataService fetchDataSource:^(</code><code>NSMutableArray</code>  <code>*array,</code><code>NSError</code> <code>*error){</code>

<code>    </code><code>if</code> <code>(!error) {</code>

<code>        </code><code>self</code><code>.dataSource=array;</code>

<code>        </code><code>[</code><code>self</code><code>.tableView reloadData];</code>

<code>}];</code>

1.棧塊,堆塊和全局塊

定義一個塊的時候,其所占的記憶體區域是在棧中的,塊隻在定義它的那個範圍有有效,我們可以先看一下下面的寫法:

<code>NSString</code>  <code>*string=@</code><code>"部落格園FlyElephant"</code><code>;</code>

<code>void</code>  <code>(^block)();</code>

<code>if</code> <code>([string isEqualToString:@</code><code>"iOS技術交流群:228407086"</code><code>]) {</code>

<code>    </code><code>block=^{</code>

<code>        </code><code>NSLog</code><code>(@</code><code>"keso"</code><code>);</code>

<code>    </code><code>};</code>

<code>}</code><code>else</code><code>{</code>

<code>        </code><code>NSLog</code><code>(@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>);</code>

先定義了block,之後在判斷語句中對block進行指派,最終棧中儲存兩個塊的記憶體,在判斷語句之外調用block有可能會把配置設定給塊的記憶體覆寫,最終造成的結果就是有的時候正确,被覆寫的時候就會造成程式崩潰,解決上面問題的方式我們可以通過block從棧記憶體中通過copy存儲在堆記憶體中,代碼如下:

<code>    </code><code>block=[^{</code>

<code>    </code><code>} </code><code>copy</code><code>];</code>

存儲在堆中的塊就變成了引用計算類型,當引用計數變成0在ARC的環境下的就會被系統回收,而棧中的記憶體是由系統自動回收的,是以第一段代碼穩定性不能保證,還有一種是全局塊,将全局塊聲明在全局記憶體中,編譯期就已經确定,不需要每次用到的在棧中建立,全局塊的拷貝是一個空操作,是以全局塊不可能被系統回收。

2.通過typedef簡化代碼可讀性

Block回調中我們發現傳入一個塊的對象寫法有的時候看起來實在不是那麼簡單明了,我們可以通過typedef簡化定義一個塊:

<code>typedef</code> <code>void</code>  <code>(^FetchBlock)(</code><code>NSMutableArray</code>  <code>*dataSouce,</code><code>NSError</code>  <code>*error);</code>

DataService中方法就可以簡化了不少:

<code>-(</code><code>void</code><code>)fetchDataSourceSimple:(FetchBlock)block;</code>

實作代碼和之前的block實作一樣:

<code>-(</code><code>void</code><code>)fetchDataSourceSimple:(FetchBlock)block{</code>

<code>        </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"部落格園"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技術交流群:228407086"</code><code>, </code><code>nil</code><code>];</code>

<code>        </code><code>block(mutableArray,</code><code>nil</code><code>);</code>

行筆匆匆,難免遺漏,如有不當,多多指教~

本文轉自Fly_Elephant部落格園部落格,原文連結:http://www.cnblogs.com/xiaofeixiang/p/4666796.html,如需轉載請自行聯系原作者

繼續閱讀