Objective-C Block沐悦,從0到1(1)

“block”? “塊”?

相信有C語言編程基礎的童鞋們對于block一定不會感到陌生五督,用咱們漢語說藏否,block就是“塊”。對于從沒接觸過block的童鞋充包,大家一定會很疑惑到底什么是“塊”副签,難道就是一坨代碼嗎?從某種角度來說“一坨”這個詞用的并沒有錯基矮。那么讓我們看看什么是“塊”吧淆储!

“塊” 是一種可在C,C++及Objective-C代碼中使用的“詞法閉包”,開發(fā)者可將代碼像對象一樣傳遞家浇,令其在不同環(huán)境下運行本砰。在定義“塊”的范圍內(nèi),它可以訪問到其中的全部變量蓝谨。

如何定義block灌具?

1,最簡單的block

^{
  //我就是個block
};

看到這樣的花括號是不是覺得很奇葩譬巫,沒錯這就是一個沒有變量名咖楣,沒有返回值,沒有參數(shù)的“三無block”芦昔。但是大家一定要記住"^",如果沒有它诱贿,那么這個block就真的成了花括號了。

2, 聲明一個block
block的聲明形式:
return_type (^block_name) (parameters)

舉個例子:

int (^oneBlock) (NSInteger a, NSNumber *b);

在這里我們就聲明了一個叫做oneBlock的block變量咕缎,它接受兩個參數(shù)珠十,并且返回值類型為int。

3凭豪,定義一個block

void (^clickBlock) (UIButton *btn);
clickBlock = ^(UIButton *btn) {
  NSLog(@"Button tag:%ld",btn.tag);
}

以上代碼中焙蹭,我們先聲明了一個clickBlock,之后又對這個block進行了定義。

double (^ totalBlock) (double a , double b) = ^double (double a, double b) {
  return a + b;
}

以上代碼我們在聲明block的同時對它進行了定義嫂伞。在這里聲明部分的返回值double是可以省略不寫的孔厉。因此可以寫成這樣:

double (^ totalBlock) (double a , double b) = ^(double a, double b) {
  return a + b;
}

4, 使用block
我們聲明了block,定義了block帖努,接下來當然是要使用它了撰豺。

int (^addBlock) (int a, int b) = ^(int a, int b) {
  return a + b;
}

int addition = addBlock (5, 10); //addition = 15

在這里,addBlock的使用方法就如同我們調(diào)用函數(shù)一樣拼余。傳入?yún)?shù)仰冠,獲得返回值疲牵。

除了以上這種簡單的使用,下面要介紹的可以說是在使用block過程中的大殺器思币,內(nèi)聯(lián)塊(inline block)。
以下的代碼來自于我對于AFNetwroking的簡單封裝,大家可以從中看到內(nèi)聯(lián)塊的使用方法。

#import <AFNetworking/AFNetworking.h>

/* Http Request Type */
typedef NS_ENUM(NSUInteger,HttpRequestType){
    HttpRequestTypeGet = 0,
    HttpRequestTypePost
};

/* Block for request success */
typedef void(^requestSuccess) (NSDictionary *object);

/* Block for request failed */
typedef void(^requestFailure)(NSError *error);

/* Block for upload progress */
typedef void(^uploadProgress)(float progress);

/* Block for dowload progress */
typedef void(^downloadProgress)(float progress);




@interface AFNetworkingTools : AFHTTPSessionManager

/* Create singleton instance */
+(instancetype) sharedManager;

+(void) requestWithType:(HttpRequestType) type withUrlString:(NSString *) urlStr withParameters:(id) parameters withSuccessBlock:(requestSuccess) successBlock withFailureBlock:(requestFailure) failureBlock progress:(downloadProgress) progress;


@end

從以上代碼我們可以看到,首先我聲明了四個block躲惰,之后我將block當作參數(shù)寫進了我定義的類方法里。接下來讓我們看看這個類方法是如何定義的变抽。

+(void) requestWithType:(HttpRequestType)type withUrlString:(NSString *)urlStr withParameters:(id)parameters withSuccessBlock:(requestSuccess)successBlock withFailureBlock:(requestFailure)failureBlock progress:(downloadProgress)progress {
    
    switch (type) {
        case HttpRequestTypeGet: {
            [[AFNetworkingTools sharedManager] GET:urlStr parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
//                progress(downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                successBlock(responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                failureBlock(error);
            }];
            break;
        }
        case HttpRequestTypePost: {
            [[AFNetworkingTools sharedManager] POST:urlStr parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
                progress(uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                successBlock(responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                failureBlock(error);
            }];
            break;
        }
        default:
            break;
    }
}

在上面的代碼中础拨,我在自己定義的類方法中調(diào)用了作為參數(shù)傳遞的block,并且把相應的值作為參數(shù)寫入了被調(diào)用的block中绍载。
看到這些你可能有些迷惑诡宗,我們把block作為參數(shù)進行了傳遞,并且對這些block進行了調(diào)用击儡,但是這些block并沒有定義呀塔沃,那么這些block具體做了什么工作呢?別著急阳谍,block的定義馬上就來蛀柴。

[AFNetworkingTools requestWithType:HttpRequestTypeGet withUrlString:urlStr withParameters:nil withSuccessBlock:^(NSDictionary *object) {
        [self fetchData:object];
        
    } withFailureBlock:^(NSError *error) {
        NSLog(@"Error:%@",error.localizedDescription);
    } progress:nil];
    

看到這里是不是有些眼熟,沒錯矫夯。block的定義就在這里鸽疾,當我們調(diào)用AFNetworkingTools的類方法時,我們會對當做參數(shù)傳遞進來的block進行定義训貌。與此同時制肮,我們也將獲得block在被調(diào)用時傳遞過來的參數(shù)。也就是第二部分代碼所傳的參數(shù)递沪。

看到這里你也許會感到疑惑豺鼻,廢了這么多功夫我們?yōu)槭裁匆褂胋lock呢?為什么不直接把(NSDictionary *object),(NSError *error)這些參數(shù)傳遞過來不就行了款慨,何必再使用block呢儒飒?

我在剛學習block的時候也不明白這個道理,在這里我想說的是檩奠,其實AFNetworkingTools 繼承了AFNetworking這個網(wǎng)絡請求第三方庫约素,因此我們在調(diào)用方法的時候進行了異步調(diào)用,所以我們并不能確定參數(shù)什么時候返回笆凌。因此,我們需要使用block作為參數(shù)返回時的橋梁去傳遞參數(shù)士葫。因為當我定義的block被調(diào)用的時候乞而,我們可以確定AFNetworking的異步調(diào)用已經(jīng)結束,我們可以拿到正確的返回值慢显。

從這里我們也可以看出爪模,block是一個有效傳遞參數(shù)的方法欠啤,并且它降低了代碼的耦合性。因為當我們更改block的定義的時候并不會改變block被調(diào)用時的實現(xiàn)屋灌。這也使得我們的代碼更加靈活洁段。

后記

在下一篇文章中,我將介紹block捕獲變量時需要注意些什么共郭,為什么有些變量能被block改變祠丝,有些則不行,為什么說可以把block當做對象看待除嘹,以及block的內(nèi)部結構以及它在內(nèi)存中的不同形式写半。如果你覺得這篇文章對你有用請點個贊吧,也希望你能關注我的簡書尉咕。你的支持將是我不斷提高自己的動力叠蝇!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市年缎,隨后出現(xiàn)的幾起案子悔捶,更是在濱河造成了極大的恐慌,老刑警劉巖单芜,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜕该,死亡現(xiàn)場離奇詭異,居然都是意外死亡缓溅,警方通過查閱死者的電腦和手機蛇损,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坛怪,“玉大人淤齐,你說我怎么就攤上這事⊥嗄洌” “怎么了更啄?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長居灯。 經(jīng)常有香客問我祭务,道長,這世上最難降的妖魔是什么怪嫌? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任义锥,我火速辦了婚禮,結果婚禮上岩灭,老公的妹妹穿的比我還像新娘拌倍。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布柱恤。 她就那樣靜靜地躺著数初,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梗顺。 梳的紋絲不亂的頭發(fā)上泡孩,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音寺谤,去河邊找鬼仑鸥。 笑死,一個胖子當著我的面吹牛矗漾,可吹牛的內(nèi)容都是我干的锈候。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼敞贡,長吁一口氣:“原來是場噩夢啊……” “哼泵琳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起誊役,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤获列,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蛔垢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體击孩,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年鹏漆,在試婚紗的時候發(fā)現(xiàn)自己被綠了巩梢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡艺玲,死狀恐怖括蝠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饭聚,我是刑警寧澤忌警,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站秒梳,受9級特大地震影響法绵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酪碘,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一朋譬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兴垦,春花似錦此熬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扶关,卻和暖如春阴汇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背节槐。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工搀庶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铜异。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓哥倔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揍庄。 傳聞我的和親對象是個殘疾皇子咆蒿,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

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