iOS之輕松上手block(上)

導(dǎo)語(yǔ)

不會(huì)使用block的iOS程序員,不是一個(gè)合格的程序員
學(xué)會(huì)了block也拜,你再也不想用繁瑣的代理
block沒有你想象中的那么難,不要害怕趾痘,不要畏懼慢哈,勇敢嘗試
筆者入行iOS時(shí)已經(jīng)是ARC的天下,所以這里只說ARC環(huán)境下的使用

什么是block

block其實(shí)就是一個(gè)代碼塊永票,把你想要執(zhí)行的代碼封裝在這個(gè)代碼塊里卵贱,等到需要的時(shí)候再去調(diào)用。那block是OC對(duì)象嗎侣集?答案是肯定的

來自官方文檔

筆者以英語(yǔ)3.9級(jí)的水平給大家翻譯下键俱,“block是一個(gè)OC對(duì)象,這意味著它能被添加到集合世分,比如NSArray方妖、NSDictionary”

block的定義

  1. block屬性或變量
    格式:返回值類型(^block名稱)(參數(shù)列表)

     /*定義屬性,block屬性可以用strong修飾罚攀,也可以用copy修飾
      有小伙伴留言說蘋果官方建議用copy党觅,筆者查了下文檔,
      確實(shí)是這樣的,不過筆者未測(cè)試出copy與strong的區(qū)別斋泄,大家喜歡啥就用啥吧*/
     @property (nonatomic, strong) void(^myBlock)();//無參無返回值
     @property (nonatomic, strong) void(^myBlock1)(NSString *);//帶參數(shù)
     @property (nonatomic, strong) NSString *(^myBlock2)(NSString *);//帶參數(shù)與返回值
     //定義變量
     void(^myBlock)() = nil;//無參無返回值
     void(^myBlock1)(NSString *) = nil;//帶參數(shù)
     NSString *(^myBlock2)(NSString *) = nil;//帶參數(shù)與返回值
    
  2. block被當(dāng)做方法的參數(shù)
    格式:(block類型)參數(shù)名稱

     - (void)test:(void(^)())testBlock//無慘無返回值
     - (void)test1:(void(^)(NSString *))testBlock//帶參數(shù)
     - (void)test2:(NSString *(^)(NSString *))testBlock//帶參數(shù)與返回值
    
  3. 使用typedef定義block

     typedef void(^myBlock)(); //以后就可以使用myBlock定義無參無返回值的block
     typedef void(^myBlock1)(NSString *); //使用myBlock1定義參數(shù)類型為NSString的block
     typedef NSString *(^myBlock2)(NSString *); //使用myBlock2定義參數(shù)類型為NSString杯瞻,返回值也為NSString的block
     //定義屬性
     @property (nonatomic, strong) myBlock testBlock;
     //定義變量
     myBlock testBlock = nil;
     //當(dāng)做參數(shù)
     - (void)test:(myBlock)testBlock;
    

block的賦值

格式:block = ^返回值類型(參數(shù)列表){}

  1. 沒有參數(shù)沒有返回值

    myBlock testBlock = ^void(){
         NSLog(@"test");
     };
     //沒有返回值炫掐,void可以省略
    myBlock testBlock1 = ^(){
         NSLog(@"test1");
     }魁莉;
     //沒有參數(shù),小括號(hào)也可以省略
     myBlock testBlock2 = ^{
         NSLog(@"test2");
     };
    
  2. 有參數(shù)沒有返回值

    myBlock1 testBlock = ^void(NSString *str) {
          NSLog(str);
    }
    //省略void
    myBlock1 testBlock = ^(NSString *str) {
          NSLog(str);
    }
    
  3. 有參數(shù)有返回值

    myBlock2 testBlock = ^NSString *(NSString *str) {
         NSLog(str)
         return @"hi";
    }
    //有返回值時(shí)也可以省略返回值類型
     myBlock2 testBlock2 = ^(NSString *str) {
         NSLog(str)
         return @"hi";
    }
    

實(shí)戰(zhàn)

接下來旗唁,我們就結(jié)合一個(gè)實(shí)例程序畦浓,來看看block在實(shí)際開發(fā)中的簡(jiǎn)單使用



本案例涉及到兩個(gè)控制器與一個(gè)Person類

  1. 聯(lián)系人列表控制器:使用tableView展示聯(lián)系人列表,稱為A控制器
  1. 新建聯(lián)系人控制器:創(chuàng)建新的聯(lián)系人對(duì)象检疫,稱為B控制器
  2. Person:聯(lián)系人讶请,有兩個(gè)屬性,name與phoneNumber

任務(wù)需求:點(diǎn)擊A控制器右上角“新建”按鈕跳到B控制器屎媳,B控制器添加聯(lián)系人后夺溢,點(diǎn)擊“保存”按鈕返回A控制器,并將新添加的聯(lián)系人展示到列表中

問題來了烛谊,如何將B控制器中的數(shù)據(jù)傳遞給A控制器呢风响?

那還不簡(jiǎn)單,A控制器直接把聯(lián)系人數(shù)組傳遞給B控制器丹禀,B控制器新建聯(lián)系人后添加到數(shù)組中状勤,然后返回A控制器,在A控制器的viewWillAppear方法中刷新表格就OK了双泪。

方法可行持搜,但是不得不說,相當(dāng)low攒读,B控制器是用來添加聯(lián)系人的朵诫,至于聯(lián)系人數(shù)組什么情況,無需關(guān)心薄扁,所以剪返,不要把數(shù)組傳遞給B控制器

B控制器要做的僅僅只是,新建聯(lián)系人邓梅,然后把聯(lián)系人對(duì)象傳遞給A控制器脱盲,至于A控制器拿到聯(lián)系人后會(huì)做什么,那是A的事情日缨,與B無關(guān)

看到這里钱反,很多人可能已經(jīng)想到了代理,沒錯(cuò)匣距,代理也可以實(shí)現(xiàn)面哥,但...是...,B控制器定義協(xié)議毅待,聲明代理方法尚卫,A控制器設(shè)置代理,遵守協(xié)議尸红,然后實(shí)現(xiàn)代理方法吱涉,B控制器在合適的地方調(diào)用代理方法刹泄,臥槽,好麻煩有木有怎爵,筆者都不想寫代碼了特石,還是回家種田去吧

好了不廢話了,進(jìn)入正題

使用block傳遞數(shù)據(jù)

  1. 在B控制器的.h文件中定義一個(gè)沒有返回值鳖链,參數(shù)類型為Person的block屬性

     @property (nonatomic, strong) void(^saveBlock)(Person *);
    
  2. 在B控制器“保存”按鈕的點(diǎn)擊方法中調(diào)用block

     - (IBAction)save:(id)sender {
         //使用事先定義好的類方法創(chuàng)建Person對(duì)象
      Person *person = [Person personWithName:_nameText.text phoneNumber:_phoneNumberText.text];
       /**調(diào)用block之前最好先判斷block是否為空姆蘸,不為空才調(diào)用,否則程序崩潰*/
       //裝逼寫法
     //!self.saveBlock? : self.saveBlock(person);
       //一般寫法
       if (self.saveBlock) {
           self.saveBlock(person);
       }
      [self.navigationController popViewControllerAnimated:YES];
     }
    
  3. 在A控制器中撒轮,給B控制器的block屬性進(jìn)行賦值

       //“新建”按鈕點(diǎn)擊執(zhí)行的方法
       - (void)newContact {
         AddContactViewController *addVC = [[AddContactViewController alloc] init];
         addVC.saveBlock = ^(Person *person){
              //這里就可以拿到B控制器傳遞過來的person對(duì)象乞旦,添加到數(shù)組然后刷新表格
          [self.contactList addObject:person];
          [self.tableView reloadData];
         };
         [self.navigationController pushViewController:addVC animated:YES];
        }
    

三步就搞定贼穆,很簡(jiǎn)單是不是题山,所以說,block并沒有你們想想的那么復(fù)雜故痊,自從筆者學(xué)會(huì)了block顶瞳,就再也沒用過代理,除了系統(tǒng)的愕秫。

block常見雷區(qū)---循環(huán)引用

使用block有一個(gè)特別要注意的地方慨菱,循環(huán)引用,何為循環(huán)引用戴甩?你引用我符喝,我引用你,誰(shuí)也不釋放誰(shuí)甜孤,對(duì)象無法銷毀协饲,占用內(nèi)存

我們來看一個(gè)循環(huán)引用的一個(gè)例子



注意看控制臺(tái)輸出,當(dāng)點(diǎn)擊“取消”時(shí)缴川,B控制器被銷毀茉稠,dealloc方法被調(diào)用

把注釋掉的代碼打開,再運(yùn)行



點(diǎn)擊“取消”按鈕把夸,B被移除而线,但是dealloc方法沒有調(diào)用,所以說恋日,B控制器并沒有銷毀膀篮,why?

block對(duì)象賦值給了B控制器的屬性岂膳,因此B會(huì)對(duì)block有一個(gè)強(qiáng)引用誓竿,而block中又用到了self(B控制器對(duì)象),block會(huì)對(duì)使用到的外部變量進(jìn)行捕獲闷营,所以烤黍,block對(duì)B控制器也有一個(gè)強(qiáng)引用知市,最終造成循環(huán)引用,誰(shuí)也無法釋放

循環(huán)引用解決方法

循環(huán)引用如何解決速蕊?很簡(jiǎn)單嫂丙,一行代碼搞定



使用weakSelf(名稱隨便取的)替代self,block將不再對(duì)self進(jìn)行強(qiáng)引用
圖中__weak也可使用__unsafe_unretained规哲,區(qū)別就是__weak修飾的指針跟啤,當(dāng)對(duì)象銷毀后,指針會(huì)被自動(dòng)置為nil唉锌,而__unsafe_unretained修飾的指針隅肥,當(dāng)對(duì)象銷毀后會(huì)變成野指針,為了安全袄简,推薦使用__weak

如此簡(jiǎn)單又好用的block腥放,你是否已經(jīng)學(xué)會(huì)了呢,如果覺得筆者的文章對(duì)你有幫助绿语,請(qǐng)多多關(guān)注秃症,你們的關(guān)注,將是筆者更新的動(dòng)力吕粹,筆者將在下篇文章中种柑,講述block在內(nèi)存中的情況,以及block對(duì)外界變量的捕獲

傳送門:《iOS之輕松上手block(下)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匹耕,一起剝皮案震驚了整個(gè)濱河市聚请,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稳其,老刑警劉巖驶赏,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異欢际,居然都是意外死亡母市,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門损趋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來患久,“玉大人,你說我怎么就攤上這事浑槽〗В” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵桐玻,是天一觀的道長(zhǎng)篙挽。 經(jīng)常有香客問我,道長(zhǎng)镊靴,這世上最難降的妖魔是什么铣卡? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任链韭,我火速辦了婚禮,結(jié)果婚禮上煮落,老公的妹妹穿的比我還像新娘敞峭。我一直安慰自己,他們只是感情好蝉仇,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布旋讹。 她就那樣靜靜地躺著,像睡著了一般轿衔。 火紅的嫁衣襯著肌膚如雪沉迹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天害驹,我揣著相機(jī)與錄音鞭呕,去河邊找鬼。 笑死裙秋,一個(gè)胖子當(dāng)著我的面吹牛琅拌,可吹牛的內(nèi)容都是我干的缨伊。 我是一名探鬼主播摘刑,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼刻坊!你這毒婦竟也來了枷恕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谭胚,失蹤者是張志新(化名)和其女友劉穎徐块,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灾而,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胡控,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旁趟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昼激。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锡搜,靈堂內(nèi)的尸體忽然破棺而出橙困,到底是詐尸還是另有隱情,我是刑警寧澤耕餐,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布凡傅,位于F島的核電站,受9級(jí)特大地震影響肠缔,放射性物質(zhì)發(fā)生泄漏夏跷。R本人自食惡果不足惜哼转,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望槽华。 院中可真熱鬧释簿,春花似錦、人聲如沸硼莽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)懂鸵。三九已至偏螺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匆光,已是汗流浹背套像。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留终息,地道東北人夺巩。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像周崭,于是被迫代替她去往敵國(guó)和親柳譬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對(duì)C語(yǔ)言的擴(kuò)展,用來實(shí)現(xiàn)匿名函數(shù)的特性,B...
    smile刺客閱讀 2,330評(píng)論 2 26
  • Block使用場(chǎng)景续镇,可以在兩個(gè)界面的傳值美澳,也可以對(duì)代碼封裝作為參數(shù)的傳遞等。用過GCD就知道Block的精妙之處摸航。...
    Coder_JMicheal閱讀 716評(píng)論 2 1
  • 前言 Blocks是C語(yǔ)言的擴(kuò)充功能制跟,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,757評(píng)論 0 23
  • block.png iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對(duì)C語(yǔ)言的擴(kuò)展,用來實(shí)...
    全棧農(nóng)民工閱讀 588評(píng)論 0 1
  • 概述 在C#異步編程時(shí)我們經(jīng)常進(jìn)行函數(shù)回調(diào),由于函數(shù)調(diào)用時(shí)異步執(zhí)行的酱虎,如果我們想讓一個(gè)操作執(zhí)行完成之后再執(zhí)行另一個(gè)...
    宋進(jìn)鋒閱讀 17,954評(píng)論 1 7