Block

基本使用

<returntype> (^blockname) (list of arguments) = ^(arguments) {body ;} ;

其中返回類型和參數(shù)可以省略

聲明

按照<returnValue> (^blockName) (parameters)的方式進行block聲明未免麻煩了些厨内,可以通過關(guān)鍵字typedef為block類型命名,然后直接通過類型名進行block創(chuàng)建渺贤。

  • 命名
typedef <returntype> (^blockname)(list of arguments) ;
  • 創(chuàng)建
blockname block = ^(arguments) {body ;} ;

__block關(guān)鍵字

CGPoint center = CGPointZero ;
CGPoint (^pointAddHandler)(CGPoint addPoint) = ^(CGPoint addPoint) {
     return CGPointMake(center.x + addPoint.x, center.y + addPoint.y) ;
 }
center = CGPointMake(100, 100) ;
NSLog(@"%@", pointAddHandler(CGPointMake(10, 10))) ;   //輸出{10,10}

block在捕獲變量的時候會保存變量被捕獲時的狀態(tài)(對象變量除外)雏胃,之后即便變量再次改變,block中變量的值也不會發(fā)生改變志鞍。所以上述代碼在計算新的坐標值時center的值依舊為CGPointZero丑掺。如果希望在block中修改外界的本地變量,可以通過給這些變量加上__block關(guān)鍵字來實現(xiàn)述雾。

循環(huán)引用

如果A創(chuàng)建并引用了B街州,B引用了callBackBlock兼丰,而callBackBlock中又引用了A,那么就會形成循環(huán)引用唆缴。解決方法是使用弱引用來解除這個循環(huán):__weak typeof(A) weakA = A ;鳍征。但是如何理解block引起的循環(huán)引用問題呢?

創(chuàng)建一個BlockTestObject類面徽,它的兩個屬性如下:

@property (nonatomic, copy) NSString *str ;
@property (nonatomic, copy) void(^myBlock)() ;

測試代碼如下:

BlockTestObject *myTest = [[BlockTestObject alloc] init] ;
myTest.str = @"這是一個測試";
myTest.myBlock= ^{
    NSLog(@"%@",myTest.str) ;
} ;
myTest.myBlock() ;

如果block代碼塊的內(nèi)部使用了外部的強引用對象艳丛,那么block代碼塊內(nèi)部就會自動生成一個強引用指向該對象。上述代碼中趟紊,myBlock會自動生成一個強引用指向myTest對象氮双,而myTest對象又有強引用指向myBlock,于是便造成了循環(huán)引用霎匈,使myTest對象無法被銷毀戴差。

解決這個問題常用方法就是使用 __weak
添加宏#define weakSelf(object) __weak typeof(object) weak##object = object ;铛嘱,測試代碼修改為:

BlockTestObject *myTest = [[BlockTestObject alloc] init] ;
myTest.str = @"這是一個測試" ;
weakSelf(myTest) ;
myTest.myBlock = ^{
  NSLog(@"%@",weakmyTest.str) ;
} ;
myTest.myBlock() ;

如果block代碼塊的內(nèi)部使用了外部的弱引用對象暖释,那么block代碼塊內(nèi)部就會自動生成一個弱引用指向該對象。上述代碼中墨吓,myBlock使用了弱引用對象weakmyTest球匕,因此myBlock只會生成一個弱引用指向?qū)ο髆yTest,從而不會造成循環(huán)引用帖烘。

由于僅有一個弱引用指向?qū)ο髆yTest亮曹,因此如果myBlock中的代碼出現(xiàn)延時執(zhí)行的情況,那么在該代碼執(zhí)行前對象myTest就有可能被銷毀秘症。測試代碼修改為:

BlockTestObject *myTest = [[BlockTestObject alloc] init] ;
myTest.str = @"這是一個測試" ;
weakSelf(myTest) ;
    myTest.myBlock = ^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",weakmyTest.str) ;
        }) ;
    } ;
myTest.myBlock() ;

此時打印的結(jié)果為(null)照卦,對象myTest在打印前就已經(jīng)銷毀±可以通過 __weak__strong一起使用來解決這個問題窄瘟。添加宏#define strongSelf(object) __strong typeof(object) object = weak##object ;,測試代碼修改為:

BlockTestObject *myTest = [[BlockTestObject alloc] init] ;
myTest.str = @"這是一個測試" ;
weakSelf(myTest)
myTest.myBlock = ^{
  strongSelf(myTest)
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"%@",myTest.str) ;
  }) ;
} ;
myTest.myBlock() ;

具體分析如下:

  1. 回調(diào)執(zhí)行strongSelf(myTest)這行代碼趟卸。一方面蹄葱,由于使用了外部的弱引用對象weakmyTest,因此會自動生成一個弱引用指向?qū)ο髆yTest锄列。另一方面图云,block內(nèi)部定義的局部變量strongSelf(myTest)會生成一個強引用指向?qū)ο髆yTest。
  2. GCD的dispatch_after代碼塊使用了該代碼塊外部的強引用對象myTest邻邮,因此會產(chǎn)生強引用指向?qū)ο髆yTest竣况。
  3. dispatch_after代碼塊會延遲2秒執(zhí)行,但是并不會阻塞線程筒严,因此myBlock會繼續(xù)執(zhí)行丹泉。當myBlock執(zhí)行完成時情萤,內(nèi)部的局部變量strongSelf(myTest)就會銷毀,此時myBlock內(nèi)部指向?qū)ο髆yTest的強引用也會銷毀摹恨。
  4. 最后只剩下GCD的dispatch_after代碼塊有強引用指向?qū)ο髆yTest筋岛,所以對象myTest沒有被銷毀。當延時時間結(jié)束晒哄,dispatch_after代碼塊執(zhí)行完成后就不會再有強引用指向?qū)ο髆yTest睁宰。
  5. 沒有強引用指向的對象myTest就會銷毀。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寝凌,一起剝皮案震驚了整個濱河市柒傻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌较木,老刑警劉巖红符,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劫映,居然都是意外死亡违孝,警方通過查閱死者的電腦和手機刹前,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門泳赋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喇喉,你說我怎么就攤上這事祖今。” “怎么了拣技?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵千诬,是天一觀的道長。 經(jīng)常有香客問我膏斤,道長徐绑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任莫辨,我火速辦了婚禮傲茄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沮榜。我一直安慰自己盘榨,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布蟆融。 她就那樣靜靜地躺著草巡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪型酥。 梳的紋絲不亂的頭發(fā)上山憨,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天查乒,我揣著相機與錄音,去河邊找鬼郁竟。 笑死侣颂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的枪孩。 我是一名探鬼主播憔晒,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔑舞!你這毒婦竟也來了拒担?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤攻询,失蹤者是張志新(化名)和其女友劉穎从撼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钧栖,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡低零,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拯杠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏婶。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖潭陪,靈堂內(nèi)的尸體忽然破棺而出雄妥,到底是詐尸還是另有隱情,我是刑警寧澤依溯,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布老厌,位于F島的核電站,受9級特大地震影響黎炉,放射性物質(zhì)發(fā)生泄漏枝秤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一慷嗜、第九天 我趴在偏房一處隱蔽的房頂上張望淀弹。 院中可真熱鬧,春花似錦洪添、人聲如沸垦页。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痊焊。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間薄啥,已是汗流浹背辕羽。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垄惧,地道東北人刁愿。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像到逊,于是被迫代替她去往敵國和親铣口。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 前言 Blocks是C語言的擴充功能觉壶,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,768評論 0 23
  • iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對C語言的擴展,用來實現(xiàn)匿名函數(shù)的特性,B...
    smile刺客閱讀 2,347評論 2 26
  • 在介紹Block之前通過一個簡單的應(yīng)用場景認識下Block 場景描述如下:TableView上面有多個Custom...
    黑_白_灰閱讀 1,388評論 4 29
  • 近來把《iOS與OS X多線程和內(nèi)存管理》這本書又掏出來看了一遍脑题,這本書前前后后加起來看了能有三四遍了,每次看都有...
    老司機Wicky閱讀 2,329評論 5 46
  • 一铜靶、Objective-C發(fā)展史 Objective-C從1983年誕生叔遂,已經(jīng)走過了30多年的歷程。隨著時間的推移...
    沒事蹦蹦閱讀 5,839評論 12 34