鏈?zhǔn)骄幊?/p>
-
Masonry 打點(diǎn)調(diào)用原理
之前一直好奇Masonry 框架是怎樣實(shí)現(xiàn)的撩荣,可以一直打點(diǎn)調(diào)用削罩,語法使用起來非常友好烙常,結(jié)合其他開發(fā)者博客理解了打點(diǎn)調(diào)用實(shí)現(xiàn)原理荆永,下面用一個(gè)計(jì)算器實(shí)現(xiàn)類來說明一下。
- 準(zhǔn)備工作:
創(chuàng)建 CaculatorMaker : NSObject 類
@interface CaculatorMaker : NSObject
// 用于存放計(jì)算結(jié)果
@property (nonatomic, assign) int result;
@end
1. 平常習(xí)慣的寫法是這樣的:
- (instancetype)add:(int)num{
self.result = self.result + num;
return self;
}
在外部調(diào)用:
CaculatorMaker *make = [CaculatorMaker new];
int result = [[[[make add:10] add:20] add:30] result] ;
可以看到如果調(diào)用計(jì)算次數(shù)過多般渡,代碼可讀性很差懒豹,解決辦法:參考Masonry 寫法試一下。
2. 模仿 Mansonry風(fēng)格寫一下
首先如果Mansonry 點(diǎn)進(jìn)庫里看的話驯用,可以看到他的點(diǎn)語法是通過 block 來實(shí)現(xiàn)的脸秽,此處來模仿一下:
(1)定義一個(gè)簡單的無參無返回的block調(diào)用
.h 文件聲明:
- (void(^)())add
.m 方法中實(shí)現(xiàn):
-(void (^)())add{
return ^(){
NSLog(@"block 調(diào)用啦");
};
}
外界調(diào)用:
CaculatorMaker *make = [CaculatorMaker new];
(1)NSObject *objc = make.add;
這時(shí)候斷點(diǎn)看一下 objc 類型:
po objc
<__NSGlobalBlock__: 0x102a8e0b0>
可以清楚的看到他是一個(gè) block 類型,因此我直接調(diào)用block
make.add(); 就可以看到上面在定義block 時(shí)候的打印
“block 調(diào)用啦”
至此打點(diǎn)調(diào)用語法已經(jīng)說明完畢蝴乔,總結(jié)一下就是:
聲明一個(gè) get 方法豹储,返回的是一個(gè) block,外界調(diào)用block淘这。
(2)點(diǎn)語法有了,那么他又是如何實(shí)現(xiàn)計(jì)算的呢巩剖?
在剛才block的基礎(chǔ)上我們需要傳一個(gè)參數(shù)
.h 文件聲明:
- (void(^)(int))add;
.m 方法中實(shí)現(xiàn):
-(void (^)(int))add{
return ^(int num){
self.result = self.result + num;
NSLog(@"block 調(diào)用, result==%d", self.result);
};
}
外界調(diào)用:
CaculatorMaker *make = [CaculatorMaker new];
make.add(10);
make.add(20);
make.add(30);
打印如下:
block 調(diào)用, result==10
block 調(diào)用, result==30
block 調(diào)用, result==60
此時(shí)已初步完成打點(diǎn)調(diào)用完成計(jì)算铝穷;但是存在兩個(gè)問題:
(1)計(jì)算結(jié)果只在 CaculatorMaker 內(nèi)部,我在外界調(diào)用時(shí)候不能直接拿到計(jì)算結(jié)果佳魔;
(2)無法像Masonry那樣可以連續(xù)打點(diǎn)調(diào)用曙聂,此處每計(jì)算一次就得調(diào)用一次方法。
為解決上面兩個(gè)問題鞠鲜,顯然我在計(jì)算完成的同時(shí)需要拿到 make 對(duì)象宁脊,計(jì)算結(jié)果就是 make對(duì)象的 result 屬性,有了make對(duì)象我就可以繼續(xù)打點(diǎn)調(diào)用贤姆。
在剛才add方法的基礎(chǔ)上我返回一個(gè)有返回值的block榆苞,這個(gè)block的返回值就是 make對(duì)象,如下:
.h 文件聲明:
- (CaculatorMaker* (^)(int))add;
.m 方法中實(shí)現(xiàn):
-(CaculatorMaker* (^)(int))add{
return ^(int num){
self.result = self.result + num;
NSLog(@"block 調(diào)用, result==%d", self.result);
return self;
};
}
外界調(diào)用:
CaculatorMaker *make = [CaculatorMaker new];
NSObject *objc = make.add(10).add(20).add(30);
此時(shí)查看 objc 類型
po objc
<CaculatorMaker: 0x608000018830>
可以看到是 CaculatorMaker 類型的一個(gè)對(duì)象霞捡,此時(shí)我可以通過他的 result屬性來獲取計(jì)算結(jié)果坐漏,那么最終我在外界調(diào)用計(jì)算方法并且拿到計(jì)算結(jié)果就是這樣的:
int result = make.add(10).add(20).add(30).result;
至此連續(xù) Mansonry 連續(xù)打點(diǎn)調(diào)用實(shí)現(xiàn)的基本原理已經(jīng)說明完畢,結(jié)合上面的小 Demo 總結(jié)一下就是:
- 通過block 代碼塊去保存一段代碼,此處是計(jì)算過程代碼赊琳;
- block 是一個(gè)有參數(shù)又返回值的block街夭,參數(shù)就是我們需要參與計(jì)算值的,返回值是 計(jì)算器構(gòu)造對(duì)象 make躏筏,有了返回值make對(duì)象板丽,方便我們進(jìn)行下一個(gè)計(jì)算。
擴(kuò)展一下趁尼,如果我們想在任意一個(gè)類中都可以方便的調(diào)用計(jì)算方法的話埃碱,可以通過分類來實(shí)現(xiàn),代碼如下:
#import <Foundation/Foundation.h>
@class CaculatorMaker;
@interface NSObject (Caculator)
+ (void)add:(void(^)(CaculatorMaker *make))block;
@end
#import "NSObject+Caculator.h"
#import "CaculatorMaker.h"
@implementation NSObject (Caculator)
+ (void)add:(void(^)(CaculatorMaker *))block{
CaculatorMaker *make = [CaculatorMaker new];
block(make);
}
@end
外界調(diào)用時(shí)候就是這樣的:
[NSObject add:^(CaculatorMaker *make) {
int result = make.add(5).add(6).add(18).result;
NSLog(@"result___%d",result);
}];
如有不對(duì)的地方弱卡,歡迎大家指正