使用Blocks來進(jìn)行工作(二)

Blocks能夠從封閉的空間中拿到值

除了包含可執(zhí)行的代碼誉帅,一個block同樣有能力區(qū)捕捉到封閉空間內(nèi)的狀態(tài)。打個比方說如果你將block的申明顯示在一個方法里面氧卧,在這個封閉的方法內(nèi)部獲得任何值可能就成了一件很容易的事情桃笙,像下面這樣:

-(void)testMethod {
       int anInteger = 42;

        void (^testBlock)(void) = ^{
                NSLog("@Integer is:%i",anInteger);
        };
        testBlock();
}

在這個例子中,anInteger是一個申明在block外部的變量沙绝,但是這個變量的值卻可以在block被定義了之后在其內(nèi)部被捕捉到搏明。這個變量的值只能是被捕捉到的那個值,即便你有其他具體的說明或修改闪檬,它還是當(dāng)時你捉到的那個變量值星著!這個意味著如果你想改變這個外部變量的值在你定義block和實現(xiàn)這個block這段時間之內(nèi),像下面這樣:

int anInteger = 42;
void (^testBlock)(void) = ^{
        NSLog(@"Integer is:%i",anInteger);
};
anInteger = 84;
testBlock();

通過上述例子我們可以發(fā)現(xiàn)谬以,這個變量的值在block中并沒有被影響到强饮,這個意味著日志的輸出始終會顯示:

Integer is :42

這個同樣也說明了block是無法更改原始變量的值,或者甚至是被捕捉到的值(這個被捕捉到的變量值對于block來說就是一個const的變量)

note:你可以嘗試在block內(nèi)部去修改變量值为黎,你發(fā)現(xiàn)會報錯邮丰;
另外,在block定義之前你去改變變量的值是可以的铭乾,block定義之后被捕捉到的話剪廉,這個值的外部變化對它是沒有任何影響的。

利用__block變量來共享內(nèi)存

如果你有這個需要在block內(nèi)部將捕捉到的變量值進(jìn)行修改的需求炕檩,你可以通過使用存儲類型修飾符__block來修飾原始變量斗蒋。這個意味著變量生活的內(nèi)存被分享在原始變量的詞匯范圍和任何有block聲明的范圍之間。
舉個例子來說笛质,你可能會像這樣重寫前面提到的例子:

__block int anInteger = 42;

void (^testBlock) (void) = ^{
        NSLog(@"Integer is :%i",anInteger);
};
anInteger = 84;
testBlock();

因為anInteger被申明成一個__block變量泉沾,所以它的存儲和block申明共享。這也意味著日志的輸出將會變成下面這個樣子:

Integer is :84

它同樣也意味著block可以改變原始變量的值妇押,像下面這樣:

__block int anInteger = 42;
void(^testBlock)(void) = ^{
        NSLog("@Integer is :%i",anInteger);
        anInteger = 100;
};
testBlock();
NSLog(@"Value of original variable is now:%i",anInteger);

這一次跷究,日志的輸出將會顯示:

Integer is :42
Value of original variable is now:100

你可以將Blocks作為方法或函數(shù)的參數(shù)傳遞

本章節(jié)前面講的每一個例子都是blocks直接在被定義了之后進(jìn)行調(diào)用。在實際中敲霍,blocks作為方法或函數(shù)調(diào)用中的參數(shù)傳遞也是隨處可見俊马。例如丁存,你可能會通過線程:Grand Central Dispatch 在后臺調(diào)用block,或者去定義一個block去代表重復(fù)調(diào)用的任務(wù)柴我,就比如說當(dāng)枚舉一個集合的時候解寝。

blocks同樣被用來作為回調(diào),定義任務(wù)完成時要執(zhí)行的代碼艘儒。例如聋伦,你的app可能現(xiàn)在需要通過創(chuàng)建一個復(fù)雜的任務(wù)對象去響應(yīng)一個用戶類似請求web網(wǎng)絡(luò)服務(wù)的動作。

這個很有可能通過使用代理來完成:你可能需要去創(chuàng)建一個合適的代理協(xié)議彤悔,實現(xiàn)被要求使用到的方法嘉抓,設(shè)置這個任務(wù)的代理對象,然后等待一旦這個任務(wù)結(jié)束你創(chuàng)建的代理對象去調(diào)用代理方法晕窑。

然而,Blocks可以讓這些變得更簡單卵佛,因為你可以定義一個回調(diào)行為在你初始化這個任務(wù)的時候杨赤,像下面這樣:

-(IBAction)fetchRemoteInformation:(id)sender {
        [self showProgressIndicator];

        XYZWebTask *task = ....
        
        [task beginTaskWithCallbackBlock:^{
                 [self hideProgressIndicator];
        }];
}

這個例子中,調(diào)用了一個方法去顯示進(jìn)度指示器截汪,然后創(chuàng)建并開啟一個任務(wù)疾牲。告訴回調(diào)的block在指定任務(wù)完成之后要實現(xiàn)的代碼。在這個例子中衙解,調(diào)用一個方法去隱藏進(jìn)度指示器看起來是很簡單的阳柔。但是請注意,block在回調(diào)的時候蚓峦,為了調(diào)用hideProgressIndicator方法需要去捕捉self對象舌剂。很重要的一點事在捕捉self對象的時候要格外小心。因為我們很容易就會創(chuàng)建一個循環(huán)的強(qiáng)引用暑椰。這個在之后的介紹中我們會提到霍转。

在代碼可讀性方面,這個blocks使得我們可以在一個地方就能很容易的看到任務(wù)發(fā)生的開始和結(jié)束一汽,避免了我們需要去追蹤代理方法來尋找出任務(wù)是怎么發(fā)生的避消。
聲明beginTaskWithCallbackBlock:方法可以像下面這個例子一樣:

-(void)beginTaskWithCallbackBack:(void(^)(void))callbackBlock;

(void(^)void))說明這個參數(shù)是一個沒有任何變量或返回值的block,實現(xiàn)方法可以通過一個很常規(guī)的途徑來調(diào)用這個block召夹,像下面這樣:

-(void)beginTaskWithCallbackBlock:(void(^)(void))callbackBlock {
        ...
        callbackBlock();
}

使用一個或多個參數(shù)的block方法函數(shù)也是同樣的方式:

-(void)doSomethingWithBlock:(void(^)(double,double))block {
        ...
        block(21.0,2.1);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岩喷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子监憎,更是在濱河造成了極大的恐慌纱意,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枫虏,死亡現(xiàn)場離奇詭異妇穴,居然都是意外死亡爬虱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門腾它,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跑筝,“玉大人,你說我怎么就攤上這事瞒滴∏#” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵妓忍,是天一觀的道長虏两。 經(jīng)常有香客問我,道長世剖,這世上最難降的妖魔是什么定罢? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮旁瘫,結(jié)果婚禮上祖凫,老公的妹妹穿的比我還像新娘。我一直安慰自己酬凳,他們只是感情好惠况,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宁仔,像睡著了一般稠屠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翎苫,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天权埠,我揣著相機(jī)與錄音,去河邊找鬼拉队。 笑死弊知,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粱快。 我是一名探鬼主播秩彤,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼事哭!你這毒婦竟也來了漫雷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤鳍咱,失蹤者是張志新(化名)和其女友劉穎降盹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谤辜,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蓄坏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年价捧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涡戳。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡结蟋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渔彰,到底是詐尸還是另有隱情嵌屎,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布恍涂,位于F島的核電站宝惰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏再沧。R本人自食惡果不足惜尼夺,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望产园。 院中可真熱鬧汞斧,春花似錦、人聲如沸什燕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屎即。三九已至,卻和暖如春事富,著一層夾襖步出監(jiān)牢的瞬間技俐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工统台, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留雕擂,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓贱勃,卻偏偏與公主長得像井赌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贵扰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

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

  • Blocks編程要點 目錄 簡介............................................
    xuejunjun閱讀 1,217評論 0 5
  • 《Objective-C高級編程》這本書就講了三個東西:自動引用計數(shù)仇穗、block、GCD戚绕,偏向于從原理上對這些內(nèi)容...
    WeiHing閱讀 9,804評論 10 69
  • 在編程領(lǐng)域里纹坐,一個牛逼程序員和一個二逼程序員之間的區(qū)別主要是其對所用編程語言優(yōu)秀特性的運(yùn)用方式。要說到Object...
    Jimmy_L_Wang閱讀 465評論 0 1
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,135評論 30 470
  • 昨天已是曾經(jīng) 回不過去的舊時光 幻化成記憶沉淀 你是否有過這樣的感觸? 曾經(jīng)多喜歡的人 如今再回首 你會笑笑不語 ...
    洛鐵花開閱讀 250評論 0 3