日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Block 进阶

發(fā)布時(shí)間:2025/4/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Block 进阶 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自:http://www.cnblogs.com/xiaofeixiang/p/4666796.html

?

關(guān)于Block之前有一篇文章已經(jīng)寫(xiě)過(guò)一篇文章Object-C-代碼塊Block回顧,不過(guò)寫(xiě)的比較淺顯,不能體現(xiàn)出Block在實(shí)際開(kāi)發(fā)中的重要性,關(guān)于Block的基礎(chǔ)知識(shí),可以參考之前的博客。在實(shí)際開(kāi)發(fā)中Block在回調(diào)過(guò)程中的是非常適合開(kāi)發(fā)使用,不管是蘋(píng)果的官方的接口還是一些第三方庫(kù)的接口中都用到了Block回調(diào)。很多情況下Block和GCD一起使用,最常見(jiàn)的場(chǎng)景的就是App去后臺(tái)取數(shù)據(jù)的過(guò)程中是需要時(shí)間,數(shù)據(jù)取成功之后我們才能更新UI頁(yè)面,這就是最常見(jiàn)的回調(diào)的方式,也可以通過(guò)Notification來(lái)做,如果是單個(gè)用Notification沒(méi)問(wèn)題,如果請(qǐng)求比較多的情況的,代碼量會(huì)上一個(gè)級(jí)別。

Block回調(diào)

簡(jiǎn)單的Block寫(xiě)法,返回類(lèi)型 ?Block名稱(chēng) ?參數(shù),基本上符合方法的寫(xiě)法,先看一個(gè)最簡(jiǎn)單的Block寫(xiě)法:

1 2 3 4 5 int??(^blockDemo)(int?a,int?b)=^(int?a,int?b){ ????return?a+b; }; NSLog(@"BlockDemo的結(jié)果:%d",blockDemo(90,72));

最后的結(jié)果是162,簡(jiǎn)單明了,很容易看懂,現(xiàn)在我們先通過(guò)UITableView展示后臺(tái)數(shù)據(jù),效果如下:

ViewController中的代碼,簡(jiǎn)單的實(shí)現(xiàn)了一下UITableView:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - (UITableView *)tableView { ????if?(!_tableView) { ????????_tableView = [[UITableView alloc] ??????????????????????initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds) - 10, ???????????????????????????????????????????????CGRectGetHeight(self.view.bounds) - 64) ??????????????????????style:UITableViewStylePlain]; ????????_tableView.rowHeight = 40.0; ????????_tableView.sectionHeaderHeight = 0.0; ????????_tableView.sectionFooterHeight = 0.0; ????????_tableView.dataSource =?self; ????????_tableView.delegate =?self; ????} ????return?_tableView; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ ????return?[self.dataSource count]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath?*)indexPath{ ????UITableViewCell? *cell=[[UITableViewCell alloc]init]; ????cell.textLabel.text=[self.dataSource objectAtIndex:indexPath.row]; ????return?cell; }

通過(guò)FEDataService中的fetchData取出數(shù)據(jù):

1 2 3 4 -(NSMutableArray?*)fetchData{ ????NSMutableArray??*mutableArray=[[NSMutableArray?alloc]initWithObjects:@"博客園",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技術(shù)交流群:228407086",nil]; ????return?mutableArray; }

Controller中的調(diào)用:

1 2 self.dataService=[[FEDataService alloc]init]; self.dataSource=[self.dataService? fetchData];

當(dāng)時(shí)從后臺(tái)取數(shù)據(jù)是需要時(shí)間的,而且網(wǎng)絡(luò)不一定能取出數(shù)據(jù),這個(gè)時(shí)候就可以通過(guò)Block進(jìn)行回調(diào),在DataService中重新定義了一個(gè)fetchDataSource方法:

1 -(void)fetchDataSource:(void(^)(NSMutableArray?*array,NSError?*error))fetchDataBlock;

注意這里的Block傳參的寫(xiě)法,fetchDataBlock相當(dāng)于是參數(shù)名,前面的是類(lèi)型,實(shí)現(xiàn)中加入了GCD

1 2 3 4 5 6 7 8 -(void)fetchDataSource:(void?(^)(NSMutableArray?*,?NSError?*))fetchDataBlock{ ????dispatch_time_t? time=dispatch_time(DISPATCH_TIME_NOW,?NSEC_PER_SEC*(int64_t)1.0); ????dispatch_after(time,dispatch_get_main_queue() , ^{ ?????????NSMutableArray??*mutableArray=[[NSMutableArray?alloc]initWithObjects:@"博客園",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技術(shù)交流群:228407086",nil]; ????????fetchDataBlock(mutableArray,nil); ????}); ????? }

Controller中進(jìn)行回調(diào)同樣實(shí)現(xiàn)以上效果:

1 2 3 4 5 6 [self.dataService fetchDataSource:^(NSMutableArray??*array,NSError?*error){ ????if?(!error) { ????????self.dataSource=array; ????????[self.tableView reloadData]; ????} }];

Block延伸

1.棧塊,堆塊和全局塊

定義一個(gè)塊的時(shí)候,其所占的內(nèi)存區(qū)域是在棧中的,塊只在定義它的那個(gè)范圍有有效,我們可以先看一下下面的寫(xiě)法:

1 2 3 4 5 6 7 8 9 10 11 NSString??*string=@"博客園FlyElephant"; void??(^block)(); if?([string isEqualToString:@"iOS技術(shù)交流群:228407086"]) { ????block=^{ ????????NSLog(@"keso"); ????}; }else{ ????block=^{ ????????NSLog(@"http://www.cnblogs.com/xiaofeixiang"); ????}; }

先定義了block,之后在判斷語(yǔ)句中對(duì)block進(jìn)行賦值,最終棧中保存兩個(gè)塊的內(nèi)存,在判斷語(yǔ)句之外調(diào)用block有可能會(huì)把分配給塊的內(nèi)存覆蓋,最終造成的結(jié)果就是有的時(shí)候正確,被覆寫(xiě)的時(shí)候就會(huì)造成程序崩潰,解決上面問(wèn)題的方式我們可以通過(guò)block從棧內(nèi)存中通過(guò)copy存儲(chǔ)在堆內(nèi)存中,代碼如下:

1 2 3 4 5 6 7 8 9 10 11 NSString??*string=@"博客園FlyElephant"; void??(^block)(); if?([string isEqualToString:@"iOS技術(shù)交流群:228407086"]) { ????block=[^{ ????????NSLog(@"keso"); ????}?copy]; }else{ ????block=[^{ ????????NSLog(@"http://www.cnblogs.com/xiaofeixiang"); ????}?copy]; }

存儲(chǔ)在堆中的塊就變成了引用計(jì)算類(lèi)型,當(dāng)引用計(jì)數(shù)變成0在ARC的環(huán)境下的就會(huì)被系統(tǒng)回收,而棧中的內(nèi)存是由系統(tǒng)自動(dòng)回收的,所以第一段代碼穩(wěn)定性不能保證,還有一種是全局塊,將全局塊聲明在全局內(nèi)存中,編譯期就已經(jīng)確定,不需要每次用到的在棧中創(chuàng)建,全局塊的拷貝是一個(gè)空操作,所以全局塊不可能被系統(tǒng)回收。

2.通過(guò)typedef簡(jiǎn)化代碼可讀性

Block回調(diào)中我們發(fā)現(xiàn)傳入一個(gè)塊的對(duì)象寫(xiě)法有的時(shí)候看起來(lái)實(shí)在不是那么簡(jiǎn)單明了,我們可以通過(guò)typedef簡(jiǎn)化定義一個(gè)塊:

1 typedef?void??(^FetchBlock)(NSMutableArray??*dataSouce,NSError??*error);

DataService中方法就可以簡(jiǎn)化了不少:

1 -(void)fetchDataSourceSimple:(FetchBlock)block;

實(shí)現(xiàn)代碼和之前的block實(shí)現(xiàn)一樣:

1 2 3 4 5 6 7 -(void)fetchDataSourceSimple:(FetchBlock)block{ ????dispatch_time_t? time=dispatch_time(DISPATCH_TIME_NOW,?NSEC_PER_SEC*(int64_t)1.0); ????dispatch_after(time,dispatch_get_main_queue() , ^{ ????????NSMutableArray??*mutableArray=[[NSMutableArray?alloc]initWithObjects:@"博客園",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技術(shù)交流群:228407086",?nil]; ????????block(mutableArray,nil); ????}); }

總結(jié)

以上是生活随笔為你收集整理的Block 进阶的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。