FBI WARNING:純屬個(gè)人見解,有可能是錯(cuò)誤的理解。O(∩_∩)O
block作用
1.可以傳遞數(shù)據(jù),取代代理模式很方法,代碼簡(jiǎn)潔。
2.當(dāng)做回調(diào),這是主要的用途。
寫法也簡(jiǎn)單,固定格式,照著寫就行,一般不會(huì)出錯(cuò),記得防止出現(xiàn)循環(huán)引用就行。別的沒(méi)啥。
問(wèn)題:block它是怎么傳遞數(shù)據(jù)的,回調(diào)怎么工作的。我冥思苦想一番,感覺有點(diǎn)眉目了,記錄一下,怕忘了。
一、函數(shù)。(或者叫<方法>,叫法不一樣,感覺沒(méi)啥區(qū)別)
1.1正常情況下,定義一個(gè)函數(shù)包括名字,參數(shù),返回值3部分。
1.2使用起來(lái)包括定義、實(shí)現(xiàn)、調(diào)用3步。
例如:
定義+實(shí)現(xiàn)。大括號(hào)里就是一個(gè)函數(shù)的實(shí)現(xiàn)部分,前面定義了名字和參數(shù)返回值
- (void)testFunction1WithParameter:(NSString *)title{
NSLog(@"方法1的實(shí)現(xiàn) -- %@", title);
}
調(diào)用:
[self testFunction1WithParameter:@"方法1"];
這就是函數(shù)的使用。
二、block
block是特殊函數(shù)?。?!
這點(diǎn)很重要。時(shí)時(shí)刻刻記得這一點(diǎn)。重點(diǎn):block是函數(shù)。
再?gòu)?qiáng)調(diào)一下,block就是特殊函數(shù),本質(zhì)還是函數(shù),既然是函數(shù),函數(shù)怎么用,block也怎么用,和上面函數(shù)是一樣。
蘋果用^這個(gè)符號(hào)標(biāo)記block,告訴人們看到這個(gè)符號(hào),就是個(gè)block了。沒(méi)別的意思,給這個(gè)函數(shù)加了個(gè)標(biāo)記,寫法不一樣了。
1.block也有方法名,參數(shù),返回值。和普通函數(shù)一樣。
定義一個(gè)block:和普通函數(shù)一樣,都是定義+實(shí)現(xiàn)
void(^block)() = ^(){
NSLog(@"block的實(shí)現(xiàn)");
};
這就定義了一個(gè)無(wú)參數(shù)無(wú)返回值,叫block名字的的函數(shù),用^標(biāo)記一下,大括號(hào)依然是函數(shù)的實(shí)現(xiàn)部分。
block();
執(zhí)行函數(shù),由于block是特殊的函數(shù),執(zhí)行方式和普通函數(shù)也不一樣,不用self調(diào)用,直接寫函數(shù)名字跟個(gè)小括號(hào)就行了。比較不像oc。
總結(jié):block是特殊函數(shù),特殊的地方就在于定義和調(diào)用方式和普通函數(shù)不一樣,實(shí)現(xiàn)部分沒(méi)變化,還是在大括號(hào)里面實(shí)現(xiàn)。
另外:如果定義一個(gè)字符串,NSstring *a = @"字符串";
NSstring 是類型,a是名字。
函數(shù)有沒(méi)有類型?當(dāng)然有!
block這種函數(shù)的寫法,相當(dāng)于用這個(gè)特殊符號(hào)標(biāo)記了一個(gè)函數(shù)的類型。void(block)() 這段代碼就是block的定義。有名字、參數(shù)類型、返回值類型。
所以,block的寫法可以定義一個(gè)函數(shù)的類型。這個(gè)函數(shù)的類型就是void(^)(),名字就是block。
2.經(jīng)過(guò)上面的洗腦,慢慢接受了block是函數(shù)的觀點(diǎn),和普通函數(shù)沒(méi)啥區(qū)別。就是樣子怪怪的罷了。
如果block像上面這么定義+實(shí)現(xiàn)+調(diào)用,用法其實(shí)和普通函數(shù)沒(méi)啥區(qū)別,就體現(xiàn)不出它的價(jià)值了。
注:如果block不作為參數(shù),需要在^符號(hào)后面直接寫上block名字,然后直接調(diào)用,如第1的例子。
如果作為參數(shù)需要像普通的參數(shù)那樣寫,在最后寫上block名字,如下。
//block傳遞數(shù)據(jù)
- (void)testFunction2WithParameter:(NSString *)title testBlock:(void(^)(NSString *msg))block{
NSLog(@"方法2的實(shí)現(xiàn) -- %@", title);
block(@"block的調(diào)用--傳遞數(shù)據(jù)data");
}
block參數(shù)的類型就是括號(hào)里的一串。這樣就把一個(gè)函數(shù)(用block的寫法)作為參數(shù)傳給另外一個(gè)參數(shù)了。
3.回調(diào)
理解了函數(shù)的定義、實(shí)現(xiàn)、調(diào)用,函數(shù)作為參數(shù)傳遞給另外一個(gè)函數(shù),就該說(shuō)回調(diào)了。
重點(diǎn):當(dāng)A函數(shù)作為B函數(shù)的參數(shù),那么A函數(shù)就具有了回調(diào)的功能。由于函數(shù)作為參數(shù)必須寫成block格式,所以一般說(shuō)block具有回調(diào)的功能。
上面說(shuō)了,函數(shù)的使用包括定義、實(shí)現(xiàn)、調(diào)用3步。一般定義和實(shí)現(xiàn)寫一塊。
調(diào)用寫在需要調(diào)用的地方。也就是說(shuō)函數(shù)的調(diào)用和實(shí)現(xiàn)是分開的。
比如第一部分介紹普通函數(shù)的部分,定義實(shí)現(xiàn)完了,調(diào)用的時(shí)候才走實(shí)現(xiàn)的部分,這點(diǎn)很重要。
函數(shù)A:(即block)
void(^)(NSString *msg)
把A函數(shù)作為另外一個(gè)函數(shù)的參數(shù),如下:
函數(shù)B:
//B的定義和實(shí)現(xiàn)
- (void)testFunction2WithParameter:(NSString *)title testBlock:(void(^)(NSString *msg))block{
NSLog(@"方法2的實(shí)現(xiàn) -- %@", title);
block(@"block的調(diào)用--傳遞數(shù)據(jù)data");
}
函數(shù)B的調(diào)用
[self testFunction2WithParameter:@"方法2" testBlock:^(NSString *msg) {
NSLog(@"block的實(shí)現(xiàn)");
NSLog(@"方法2的調(diào)用 -- %@", msg);
}];
后面的大括號(hào)其實(shí)是A函數(shù)的實(shí)現(xiàn)部分,這種block的寫法,其實(shí)把函數(shù)的定義、實(shí)現(xiàn)、調(diào)用都分開了。而一般函數(shù)定義和實(shí)現(xiàn)是寫一塊的,比如B函數(shù)。
但是實(shí)現(xiàn)和調(diào)用都是分開的,這點(diǎn)沒(méi)變。都是通過(guò)調(diào)用函數(shù)去實(shí)現(xiàn)大括號(hào){ }里面的代碼。
通過(guò)觀察:可以得到:
1.B函數(shù)的實(shí)現(xiàn)里面寫了block的調(diào)用,
2.B函數(shù)的調(diào)用的時(shí)候,把block實(shí)現(xiàn)了。
會(huì)出現(xiàn)什么情況?
按代碼的執(zhí)行順序
第一步、在viewDidLoad里調(diào)用B函數(shù),這是需要跳到B函數(shù)的實(shí)現(xiàn)部分,即大括號(hào)里
第二步、在B函數(shù)的實(shí)現(xiàn)里面,發(fā)現(xiàn)了A函數(shù)block的調(diào)用
第三步、既然有調(diào)用,必須去尋找怎么實(shí)現(xiàn)的,就跳到了A函數(shù)的實(shí)現(xiàn)部分
第四步、發(fā)現(xiàn)A的實(shí)現(xiàn)部分在B函數(shù)的調(diào)用后面,所以代碼又回到了B函數(shù)的調(diào)用部分,回到了第一步的代碼部分viewDidLoad里。這就實(shí)現(xiàn)了回調(diào)。

如果block帶有參數(shù),就把這個(gè)參數(shù)回調(diào)了B函數(shù)的執(zhí)行地方,可以傳遞數(shù)據(jù),這就實(shí)現(xiàn)了傳遞數(shù)據(jù)的功能。例如上面的函數(shù)傳了個(gè)字符串。比如一些網(wǎng)絡(luò)請(qǐng)求方法,通過(guò)寫一個(gè)block就能把請(qǐng)求的數(shù)據(jù)傳遞到這個(gè)請(qǐng)求方法調(diào)用的地方,就算是得到了數(shù)據(jù)。
swift閉包一個(gè)道理,捋一捋就通了。