iOS-Block的使用你看我啊

為什么題目是“Block的使用你看我啊”,而不是牛逼哄哄的“Block你看我就夠了”羞反,原因是本文并不會講解Block在C++中的實(shí)現(xiàn)部分观游,而是停留在OC語言中稽屏。主要講訴一些語法和使用奖慌。
(如果本文中有講述不對或者不準(zhǔn)確的地方歡迎大家提出來)

1抛虫、Block是什么?
 - 匿名函數(shù)
 - 截獲自動變量
2简僧、Block語法建椰。
3、Block類型變量岛马。
4棉姐、Block的用途。
 - 作為函數(shù)參數(shù)
 - 反向傳值
 - 循環(huán)引用
(delegate差不多作用啦逆,但是顯得更加簡潔)

首先就是Block是什么伞矩?用一句話來概括就是帶有自動變量的匿名函數(shù)。
那么我們解釋清楚了什么是“匿名函數(shù)”夏志,什么是“自動變量”乃坤,那么相信大家大概就對Block有了一個(gè)大概的認(rèn)識。

  • 匿名函數(shù)
    匿名函數(shù)顧名思義就是不帶名字的函數(shù)沟蔑,在C語言中不允許這樣的方法存在侥袜,而在OC中的Block則可以用指針來直接調(diào)用一個(gè)函數(shù),但雖說如此我們還是需要知道指針的名稱溉贿。(關(guān)于這點(diǎn)枫吧,額~~我們還是不要糾結(jié)的比較好∮钌~九杂!~~)
  • 自動變量
    自動變量在Block中的具體表現(xiàn)就是截獲自動變量,來看下面這一段代碼:
 int b = 0;
    void (^blo)() = ^{
        NSLog(@"Input:b=%d",b);
    };
    b = 3;
    blo();
    /**
     *    Input:b=0
     */

雖然我們在調(diào)用blo之前改變了b的值宣蠕,但是輸出的還是Block編譯時(shí)候b的值例隆,所以截獲瞬間自動變量就是:在Block中會保存變量的值,而不會隨變量的值的改變而改變抢蚀。

我們再來看一段代碼

int b = 0;
    void (^blo)() = ^{
        b = 3;
    };

這段代碼編譯出錯(cuò)镀层,編譯器提示的大概就是不能在Block中改變變量的值。因?yàn)樵?strong>Block中截獲了變量的瞬間值以后就不能再改變變量的值皿曲,如果想要在Block中改變變量的值唱逢,那么我們只需要在變量聲明的時(shí)候加上__Block修飾符,像這樣:

__block int b = 0;
    void (^blo)() = ^{
        b = 3;
    };

然而這樣的情況又是允許的:

 NSMutableArray *array = [[NSMutableArray alloc]init];
    void (^blo)() = ^{
        [array addObject:@"Obj"];
    };

為什么呢屋休,因?yàn)槲覀冎皇菍孬@的變量進(jìn)行了操作坞古,而沒有進(jìn)行賦值,所以對于截獲變量劫樟,可以進(jìn)行操作而不可以進(jìn)行賦值痪枫。

還有一點(diǎn)需要注意织堂,在Block中不可以對C語言數(shù)組進(jìn)行操作,原因是:~~~不支持奶陈。易阳。。吃粒。

結(jié)合匿名函數(shù)和截獲自動變量的特性潦俺,Block可以做很多事情,我們下面在看声搁。


我們來具體看一下Block語法的書寫,我們首先來看一個(gè)完整的Block:

 ^ NSString *(NSString *a,NSString *b){
        return a;
    };

我們來分別解釋下每一個(gè)部分都是什么東西:

  • “^”這個(gè)符號表示這是一個(gè)Block捕发;
  • NSString *表示返回值疏旨。
  • (NSString *a,NSString *b)這個(gè)括號中是Block的參數(shù),語法和C語言類似扎酷。

其實(shí)我們可以省略Block的返回值檐涝,像這樣寫:

^ (NSString *a,NSString *b){
        return a;
    };

這樣寫和上面那種寫法是一模一樣的,其實(shí)如果沒有參數(shù)列表我們甚至可以省略參數(shù)列表法挨,像這樣:

^ {
        NSLog(@"我沒有參數(shù)列表");
    };

如果把這段代碼寫完整谁榜,那么就是這樣的:

^void(void) {
        NSLog(@"我沒有參數(shù)列表");
    };

為什么需要Block變量?我們可以這樣理解凡纳,我們通過這個(gè)Block變量來獲取Block的指針窃植,然后通過這個(gè)指針就可以來使用Block函數(shù)。我們先來看一下如何聲明一個(gè)Block變量

      int (^Blo)(NSString *s1,NSString *s2);

對照前面的Block函數(shù)荐糜,我們可以比較容易的理解各個(gè)部分的含義:

他們分別是:

  • 返回值
  • 變量名
  • 參數(shù)列表

好的巷怜,然后我們用上面講到的Block語法來對這個(gè)Block變量進(jìn)行賦值:

    int (^Blo)(NSString *s1,NSString *s2);
    
    Blo = ^(NSString *s1,NSString *s2){
        return 1;
    };

然后我們就可以將這個(gè)Block變量當(dāng)作C語言函數(shù)來使用了。


那么Block到底怎么用呢暴氏?

Block能夠當(dāng)作函數(shù)參數(shù)延塑,首先我們聲明一個(gè)Block類型變量 ,并加上typedef修飾符答渔,像這樣:

typedef void(^Blo)(NSString *s1,UIColor *c);

這樣我們就可以使用Blo來表示這個(gè)Block关带,然后我就可以將Blo加入到函數(shù)參數(shù)中,我們來聲明一個(gè)函數(shù):

-(void)func:(Blo)BlockPra{
    
    BlockPra(@"Str",[UIColor redColor]);

}

然后我們可以這樣使用這個(gè)函數(shù):

[self func:^(NSString *s1, UIColor *c) {
        NSLog(@"%@",s1);
        self.view.backgroundColor = c;
    }];

是不是覺得十分眼熟沼撕,平時(shí)使用的許多回調(diào)當(dāng)中大多都是這樣的形式宋雏,可能其中其較多的就是網(wǎng)絡(luò)回調(diào)了,我們只需要調(diào)用方法务豺,然后在回調(diào)當(dāng)中就可以對結(jié)果進(jìn)行操作好芭,很多蘋果自己寫的API都是使用了這樣的方法,這樣做的好處就是形式上十份簡潔冲呢,當(dāng)然像這種地方你使用delegate肯定也是可以的舍败,但是表現(xiàn)上就沒有Block那么簡潔,使用起來也沒有Block那么方便。

除此之外邻薯,Block還可以用來作為控制器之間的一個(gè)通信裙戏。
前面我們已經(jīng)知道Blcok是一個(gè)匿名函數(shù),同時(shí)也是一個(gè)指針厕诡,那么使用Block就可以彌補(bǔ)在iOS中函數(shù)傳遞的功能累榜。通常是這么用的:

頁面B的.h文件中定義了這樣一個(gè)Block執(zhí)政,然后聲明了一個(gè)變量灵嫌,像這樣:

  typedef void(^Blo)(NSString *s1,UIColor *c);
  @property (nonatomic, copy) Blo block;

然后我們在頁面A當(dāng)中有這么一段代碼:

ViewController *b = [[ViewController alloc]init];
    
    __weak  ViewController *wself = self;
    b.block = ^(NSString *s1,UIColor *c){
        NSLog(@"%@",s1);
        wself.view.backgroundColor = c;
    };
    [self.navigationController pushViewController:b animated:true];

然后在頁面B的任意地方我們調(diào)用block變量壹罚,像這樣:

     self.block(@"str",[UIColor redColor]);

都會在A頁面中調(diào)用B頁面?zhèn)鬟^來的參數(shù),在A頁面進(jìn)行操作寿羞,對控制器A進(jìn)行改變猖凛,這樣的做法通常用做 控制器 反向傳值。

在這里有一點(diǎn)需要注意就是Block的使用引起的循環(huán)引用绪穆。如果在Block中使用附有__strong修飾符的對象類型自動變量辨泳,那么當(dāng)Block從棧復(fù)制到堆時(shí),改對象為Block所有玖院。這樣容易引起循環(huán)引用菠红,從而發(fā)生內(nèi)存泄漏,然而我們只需要保證當(dāng)前控制器也就是self在需要釋放的時(shí)候正確釋放就可以难菌,所以我們再來看上面那段代碼:

      __weak  ViewController *wself = self;

我們定義一個(gè)wself變量并加上__weak修飾符试溯,在Block代碼塊中,所有需要self的地方都用wself來替代郊酒。這樣就不會增加引用計(jì)數(shù)耍共,所以Block持有self對象也就不會造成循環(huán)引用,從而造成內(nèi)存泄漏猎塞。
不管是將Block當(dāng)作函數(shù)參數(shù)试读,還是用來反向傳值,其實(shí)都是對Block的本質(zhì)荠耽,也就是“帶有自動變量的匿名函數(shù)”的兩個(gè)修飾钩骇,“帶有自動變量”、“匿名函數(shù)”這兩個(gè)特性 的應(yīng)用铝量。


總結(jié)一下Block到底是什么倘屹、用來干什么:

  • C++中的Struct(本文未提到)。
  • 用來彌補(bǔ)iOS中函數(shù)傳遞的功能慢叨。
  • 他是一段代碼塊的內(nèi)存的指針纽匙。
  • 和delegate一樣的功能,但是顯的更加簡潔拍谐。

差不多就這樣吧烛缔,自我感覺本文是有邏輯的馏段,但是部分講解可能不是特別到位谐宙,覺得還不錯(cuò)的請關(guān)注本人疼电。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市证芭,隨后出現(xiàn)的幾起案子晕翠,更是在濱河造成了極大的恐慌喷舀,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淋肾,死亡現(xiàn)場離奇詭異硫麻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)樊卓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門拿愧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人简识,你說我怎么就攤上這事赶掖「忻停” “怎么了七扰?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長陪白。 經(jīng)常有香客問我颈走,道長,這世上最難降的妖魔是什么咱士? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任立由,我火速辦了婚禮,結(jié)果婚禮上序厉,老公的妹妹穿的比我還像新娘锐膜。我一直安慰自己,他們只是感情好弛房,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布道盏。 她就那樣靜靜地躺著,像睡著了一般文捶。 火紅的嫁衣襯著肌膚如雪荷逞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天粹排,我揣著相機(jī)與錄音种远,去河邊找鬼。 笑死顽耳,一個(gè)胖子當(dāng)著我的面吹牛坠敷,可吹牛的內(nèi)容都是我干的妙同。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼常拓,長吁一口氣:“原來是場噩夢啊……” “哼渐溶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弄抬,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茎辐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后掂恕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拖陆,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年懊亡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了依啰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡店枣,死狀恐怖速警,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸯两,我是刑警寧澤闷旧,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站钧唐,受9級特大地震影響忙灼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钝侠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一该园、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帅韧,春花似錦里初、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萧诫,卻和暖如春斥难,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帘饶。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工哑诊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人及刻。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓镀裤,卻偏偏與公主長得像竞阐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子暑劝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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