block

目錄

一您机、通常作用;

二年局、block用來解決什么問題际看?

三、為什么要用copy修飾Block矢否;

四仲闽、為什么Block中可以訪問局部變量而不能修改;

五僵朗、為什么用__block修飾的局部變量可以在Block內(nèi)部修改赖欣;

六、為什么使用Block會造成循環(huán)引用验庙,怎么解決顶吮;

在iOS4.0之后,蘋果開始引入的對C語言的擴展粪薛,對于用法我們已經(jīng)相當(dāng)?shù)氖煜ゃ擦耍谖覀兪褂肁SI的時候還是delegate橫行,切換到AFNetWorking之后违寿,block開始被大量的使用湃交。

一、通常被用來做并發(fā)任務(wù)藤巢、遍歷和回調(diào)搞莺。

并發(fā)任務(wù):在線程管理方面由NSThead->NSOperation->GCD

遍歷:forin -> enumerateObjectsUsingBlock:

回調(diào):delegate,KVO掂咒,NSNotification->block

二才沧、那么block到底是用來做什么的呢迈喉?解決什么問題呢?

讓我們先來了解一下匿名函數(shù)

匿名函數(shù):就是沒有名字的函數(shù)温圆。

匿名函數(shù)最大的用途是創(chuàng)建閉包(這是JavaScript語言的特性之一)弊添,并且還可以構(gòu)建命名空間,以減少全局變量的使用捌木。

那么看看block的使用 -(void)doSomethingWithBlock:(void^(Bool success))block;

使用這個方法,其實也使用了一個回調(diào)函數(shù)嫉戚,block是一個匿名函數(shù)刨裆。

那么閉包是什么意思呢?

閉包就是函數(shù)的嵌套彬檀,內(nèi)層的函數(shù)可以使用外層函數(shù)的所有變量帆啃,即使外層函數(shù)已經(jīng)執(zhí)行完畢。

閉包與對象之間的關(guān)系是什么窍帝?

那么我們先看一下官方文檔上怎么說努潘?

A closure lets you associate some data (the environment) with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods.

Consequently, you can use a closure anywhere that you might normally use an object with only a single method.

譯文:

閉包允許你將某些數(shù)據(jù) (環(huán)境) 與操作該數(shù)據(jù)的函數(shù)關(guān)聯(lián)起來,這與面向?qū)ο缶幊逃忻黠@的相似之處坤学,其中的對象允許我們?nèi)⒁恍?shù)據(jù)關(guān)聯(lián)一個或者更多的方法疯坤。

因此, 你可以在通常只使用單個方法的對象的任何地方使用閉包。

閉包相當(dāng)(近似)于一個只有一個方法的對象深浮,只有一個公開方法压怠,而且成員數(shù)據(jù)幾乎全私有(閉包)的對象,自然是一個緊湊版的對象了飞苇。

閉包連貫性好菌瘫,比較緊湊,因此看起來代碼比較清晰布卡。block就是iOS補充的閉包特性雨让。

為什么這么做?

前面我們提到的delegate和NSNotification都能將外部函數(shù)的所有變量傳出來忿等,為何選用block栖忠?這就是block的優(yōu)勢,緊湊以及代碼清晰贸街。

block的做法:UIButton ?*button; ?button.clickBlock = ^{};

使用delegate的時候還需要聲明娃闲,在代理中另起一行來實現(xiàn),而block讓我們看到這個對象以及這個對象的操作匾浪。

上面是從代碼清晰方面來講的皇帮,下面是功能方面:

block的提出是為了在不同的對象間除了傳遞值之外還可以傳遞一個操作而提出的。

A:

[self doSomethingWithBlock:^{log(A) }];

- (void)doSomethingWithBlock:(void(^)(void))block{ B.block = block}

B:

block();調(diào)用后蛋辈,log出A属拾。


三将谊、為什么要用copy修飾Block

為什么要用copy,這是因為在MRC時期渐白,作為屬性的block在初始化時是被存放在靜態(tài)區(qū)的尊浓,這樣在使用時如果block內(nèi)有調(diào)用外部變量,那么block無法保留其內(nèi)存纯衍,在初始化的作用域內(nèi)使用并不會有什么影響栋齿,但一但出了block的初始化作用域,就會引起崩潰襟诸,使用copy可以將block的內(nèi)存推入堆中瓦堵,這樣讓其擁有保存調(diào)用的外部變量的內(nèi)存的能力。

大部分人都認(rèn)為block作為屬性在聲明時歌亲,只能用copy修飾菇用,而不可以用strong。其實用strong也是可以的陷揪。只是使用copy修飾block是MRC時期的遺留物惋鸥,這在MRC時期是至關(guān)重要的事情,但是使用ARC的現(xiàn)在悍缠,strong是可以代替的卦绣,只是一個習(xí)慣問題而已。

四飞蚓、為什么Block中可以訪問局部變量而不能修改

例子如下:

注: 通過clang命令將OC轉(zhuǎn)為C++代碼來查看一下Block底層實現(xiàn),clang命令使用方式為終端使用cd定位到main.m文件所在文件夾,然后利用clang -rewrite-objc main.m將OC轉(zhuǎn)為C++,成功后在main.m同目錄下會生成一個main.cpp文件

由此可知,在Block定義時便是將局部變量的值傳給Block變量所指向的結(jié)構(gòu)體,因此在調(diào)用Block之前對局部變量進(jìn)行修改并不會影響B(tài)lock內(nèi)部的值,同時內(nèi)部的值也是不可修改的迎卤。

五、為什么用__block修飾的局部變量可以在Block內(nèi)部修改

添加__block修飾符之后的代碼如下:

可以看到并不是直接傳遞a的值了玷坠,而是把a的地址傳過去了蜗搔,所以在block內(nèi)部便可以修改到外面的變量了。

六八堡、為什么使用Block會造成循環(huán)引用樟凄,怎么解決

因為對象obj在Block被copy到堆上的時候自動retain了一次。因為Block不知道obj什么時候被釋放兄渺,為了不在Block使用obj前被釋放缝龄,Block retain了obj一次,在Block被釋放的時候挂谍,obj被release一次叔壤。

循環(huán)引用問題的根源在于Block和obj可能會互相強引用,互相retain對方口叙,這樣就導(dǎo)致了循環(huán)引用炼绘,最后這個Block和obj就變成了孤島,誰也釋放不了誰妄田。

解決辦法:

在ARC中沒有retain俺亮,retainCount的概念驮捍。只有強引用和弱引用的概念。當(dāng)一個變量沒有__strong的指針指向它時脚曾,就會被系統(tǒng)釋放东且。

參考以及使用了以下文章的研究:

iOS-Block探究

JavaScript中的匿名函數(shù)及函數(shù)的閉包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市本讥,隨后出現(xiàn)的幾起案子珊泳,更是在濱河造成了極大的恐慌,老刑警劉巖拷沸,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件色查,死亡現(xiàn)場離奇詭異,居然都是意外死亡堵漱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門涣仿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勤庐,“玉大人,你說我怎么就攤上這事好港∮淞” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵钧汹,是天一觀的道長丈探。 經(jīng)常有香客問我,道長拔莱,這世上最難降的妖魔是什么碗降? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮塘秦,結(jié)果婚禮上讼渊,老公的妹妹穿的比我還像新娘。我一直安慰自己尊剔,他們只是感情好爪幻,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著须误,像睡著了一般挨稿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上京痢,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天奶甘,我揣著相機與錄音,去河邊找鬼祭椰。 笑死甩十,一個胖子當(dāng)著我的面吹牛船庇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侣监,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鸭轮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了橄霉?” 一聲冷哼從身側(cè)響起窃爷,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎姓蜂,沒想到半個月后按厘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡钱慢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年逮京,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片束莫。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡懒棉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出览绿,到底是詐尸還是另有隱情策严,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布饿敲,位于F島的核電站妻导,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怀各。R本人自食惡果不足惜倔韭,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓢对。 院中可真熱鬧狐肢,春花似錦、人聲如沸沥曹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妓美。三九已至僵腺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壶栋,已是汗流浹背辰如。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贵试,地道東北人琉兜。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓凯正,卻偏偏與公主長得像,于是被迫代替她去往敵國和親豌蟋。 傳聞我的和親對象是個殘疾皇子廊散,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

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