最初見到鏈?zhǔn)秸Z法的時(shí)候是在masonry庫中,當(dāng)時(shí)看到這種寫法我是震驚的.一行代碼可以賦值多個(gè)屬性怎么一個(gè)爽字了得.一直沒有去研究寫法的實(shí)現(xiàn).直到我看了一次公開課(為了避嫌,公開課的名字就不說了).在公開課中學(xué)到了鏈?zhǔn)秸Z法的原理和寫法.
原理
一般情況下 OC 的調(diào)用方法是這樣的,比如 tableView 刷新數(shù)據(jù)的方法:
[tableView reloadData];
當(dāng)然我們也可以這樣寫:
tableView.reloadData;
雖然 Xcode 會(huì)拋出一個(gè)警告,但是并不妨礙方法的執(zhí)行.那么鏈?zhǔn)秸Z法僅僅是這么做然后加了一個(gè)括號(hào)傳遞參數(shù)嗎? 很顯然不是.如果是有參數(shù)的方法我們這么做就會(huì)拋出錯(cuò)誤.導(dǎo)致無法編譯,就像這樣:
很遺憾,這種方法不對(duì).如果可以這么做,相信很多討厭 OC 調(diào)用方法方式的人都會(huì)開心吧.那么如何能讓方法使用小括號(hào)接受參數(shù)呢?這里就需要借助 block 的語法了
block
還記得 block 怎么傳遞參數(shù)嗎?是不是這樣:
void(^block)(int i) = ^(int i){
NSLog(@"%d",i);
};
block(1);
可以看到 block 使用小括號(hào)接受參數(shù).如果一個(gè)方法返回值是一個(gè) block 并且使用.
語法調(diào)用在連接到一起是不是就成了這樣:
方法實(shí)現(xiàn):
// 返回一個(gè)接受一個(gè) int 類型參數(shù)的 block
- (void(^)(int))test{
void(^block)(int i) = ^(int i){
NSLog(@"%d",i);
};
return block;
}
方法的正常調(diào)用步驟是這樣的:
// 我們知道 self.test 就相當(dāng)于 [self test]
// 將 test 方法的返回值賦值給一個(gè) block 變量 再使用變量調(diào)用 block 中的代碼
void(^block)(int i) =self.test;
block(1);
如果連起來寫就成了這樣
// 因?yàn)?self.test 本身就返回了block
//括號(hào)中的1看似是將值賦給了 test 方法,其實(shí)是賦給了 test 方法返回的 block
self.test(1);
不得不說大牛的腦洞大的可以.很巧妙的一個(gè)方法.初步實(shí)現(xiàn)了使用括號(hào)傳遞參數(shù),接下來就要讓他們組成鏈條
鏈接
有了上面的思路.再考慮讓代碼的調(diào)用形成鏈條就簡(jiǎn)單多了,只要讓 block 返回 self 自身即可,就像這樣:
// 當(dāng)前類是ViewController類 block 返回 類對(duì)象 類對(duì)象是不是就可以繼續(xù)調(diào)用 test 方法了
- (ViewController *(^)(int))test{
ViewController *(^block)(int i) = ^ViewController *(int i){
NSLog(@"%d",i);
return self;
};
return block;
}
調(diào)用的時(shí)候就可以很爽的這么寫了:
self.test(1).test(2).test(3);
看一下輸出結(jié)果:
2017-06-14 23:40:04.268258+0800 鏈?zhǔn)秸Z法[6727:1519931] 1
2017-06-14 23:40:04.268393+0800 鏈?zhǔn)秸Z法[6727:1519931] 2
2017-06-14 23:40:04.268431+0800 鏈?zhǔn)秸Z法[6727:1519931] 3
當(dāng)然 masonry 中鏈?zhǔn)秸Z法的使用更為復(fù)雜,這里只講一下鏈?zhǔn)秸Z法的書寫原理.
鏈條的執(zhí)行順序
- self 調(diào)用 test 方法 test 方法返回 block
- block 得到小括號(hào)中的參數(shù) 并執(zhí)行 block 中的代碼
- block 返回對(duì)象 對(duì)象接著調(diào)用 test 方法 實(shí)際應(yīng)用中 test 可以是任何這種格式的方法
關(guān)于block的一些小細(xì)節(jié)
- block 是順序執(zhí)行的,并非異步執(zhí)行,你覺得他是異步執(zhí)行的很大一部分原因是因?yàn)榇蟛糠?block 是用來處理異步回調(diào)的
- 書寫時(shí)如果帶返回值的 block 在實(shí)現(xiàn)的時(shí)候
^
的位置是在最左邊,比如^ViewController *(int i)
而不是像聲明時(shí)一樣返回值類型在最左邊 - block 的實(shí)現(xiàn)可以不寫返回值類型 除非返回值類型是
id
并且返回值為nil
的情況.這時(shí)必須在實(shí)現(xiàn)聲明返回值類型是id
,否則報(bào)錯(cuò)
id(^block)() = ^id(){
// 返回 nil 必須在實(shí)現(xiàn)說明返回值類型是id
return nil;
}
id(^block)() = ^(){
// 返回 不為nil 可以不用聲明返回值
return slef;
}