提到鏈式編程和函數(shù)式編程,最典型的代表是Masonry 比較完美的實現(xiàn)了函數(shù)式編程和鏈式編程。例如
```
[view mas_makeConstraints:^(MASConstraintMaker *make) {
? ? ? ? make.top.equalTo(self.view).offset(100);
? ? ? ? make.centerX.equalTo(self.view.mas_centerX).offset(100);
? ? ? ? make.height.mas_equalTo(100);
? ? ? ? make.width.mas_equalTo(100);
? ? }];
```
? 所謂的鏈式編程其實就是 在返回值的基礎(chǔ)上繼續(xù)調(diào)用方法,那么問題來了深寥。什么樣的返回值才能調(diào)用方法,答案是返回對象 只要返回對象然后調(diào)用對應的對象方法即可實現(xiàn) 鏈式編程
? 例如 :
首先定義Person類
添加兩個對象方法
```
-(void)play;
-(void)run;
```
```
-(void)play{
? ? NSLog(@"play");
}
-(void)run{
? ? NSLog(@"run");
}
```
**在`ViewController`調(diào)用**
```
Person * xiaoming = [Person new];
[xiaoming play];
```
我們現(xiàn)在想要實現(xiàn)的是 ` [[xiaoming play]run]`,所以play方法返回值就不能為空,應該是Person對象
```
-(Person *)play;
-(Person *)play{
? ? return self;
}
```
我們已經(jīng)實現(xiàn)了`[[xiaoming play]run]`
這樣的鏈式編程 和Masonry 確實有點相差甚遠
我們知道在OC中的方法調(diào)用是 發(fā)送消息的方式實現(xiàn)的那么 要實現(xiàn) person.eat 該怎么實現(xiàn)呢?
那么我們?nèi)绾螌崿F(xiàn)` .`方法呢
```
-(void(^)(void))play2;
```
```
-(void (^)(void))play2{
? ? return ^(){
? ? ? ? NSLog(@"play2");
? ? };
}
```
即可實現(xiàn) `[xiaoming play].play2();`
然而后邊如果想要添加點方法窗骑,實現(xiàn)方法相同,只需返回均為Person對象即可漆枚。
```
-(Person *(^)(NSString * str))play2;
-(void(^)(NSString * str))play3;
```
```
- (Person *(^)(NSString *str))play2{
? ? return ^(NSString *str){
? ? ? ? NSLog(@"%@",str);
? ? ? ? return self;
? ? };
}
-(void (^)(NSString * str))play3{
? ? return ^(NSString * str){
? ? ? ? NSLog(@"%@",str);
? ? };
}
```
即可實現(xiàn)` xiaoming.play2(@"33").play3(@"333");`
上面的方法是通過block返回值為當前對象创译,即可實現(xiàn)點語法連續(xù)調(diào)用。
## 構(gòu)造方法
函數(shù)式編程 就是通過類似于 函數(shù)調(diào)用的方式實現(xiàn)想要的功能即 method(); 這樣的方式,
那么我們知道在OC能用method() 這樣調(diào)用,只有一個可以實現(xiàn),那就是BLOCK, 我們在調(diào)用BLOCK時 不就是這樣調(diào)用的嗎?? 那么我們知道只要我的一個方法的返回值是BLOCK的時候就可以使用函數(shù)式調(diào)用墙基。
**定義構(gòu)造方法**
```
+(instancetype)initWithP:(void(^)(Person * p))Block;
```
```
+(instancetype)initWithP:(void (^)(Person *))Block{
? ? Person * p = [Person new];
? ? return p;
}
```
可以調(diào)用返回值為p的函數(shù)式構(gòu)造方法软族,然后在內(nèi)部對p對象進行使用;
```
[Person initWithP:^(Person *p) {
? ? }];
```
即可調(diào)用鏈式方法
```
[Person initWithP:^(Person *p) {
? ? ? ? ? p.play2(@"222").play3(@"3333");
? ? }];
```
## 定義成員屬性實現(xiàn)點語法
上面均是通過定義方法實現(xiàn)點語法調(diào)用残制,但是我們的編程習慣的用點語法調(diào)取類的成員屬性立砸。`OC`中的點語法,`.XX`是`getter`初茶,`.XX=XXX`颗祝;是`setter`,顯然鏈式編程是一串的恼布,所以我們應該想到將`block`聲明為屬性螺戳,并且在這些`block`屬性的`getter`方法中做一些事情。
**person類添加成員屬性**
```
@property(nonatomic,readonly,copy)Person *(^eat)(NSString * str);
```
**重寫成員屬性getter方法**
```
-(Person *(^)(NSString *))eat{
? ? return ^(NSString* eat){
? ? ? ? NSLog(@"%@",eat);
? ? ? ? return self;
? ? };
}
```
所以我們就可以實現(xiàn)點調(diào)用`eat`方法折汞。
```
? ? [Person initWithP:^(Person *p) {
? ? ? ? p.play2(@"222").eat(@"333").play3(@"444");
? ? }];
```
定義屬性相比定義方法一個突出的優(yōu)點就是輸入的時候會有輸入提示吹菱,所以更常用著摔。?
## 舉例說明:
**我們現(xiàn)在要在VC上加四個大小相同钉凌,圓角為2的紅色view,實現(xiàn)代碼如下**
```
@interface MYView : UIView
+(instancetype)initWith:(void(^)(MYView *view))BLOCK;
@property(nonatomic,readonly,copy)MYView *(^viewFrame)(CGRect? frame);
@property(nonatomic,readonly,copy)MYView * (^layerCornerRadious)(CGFloat radious);
@property(nonatomic,copy,readonly)MYView*(^ColorString)(NSString * colorStr);
@end
```
```
+(instancetype)initWith:(void (^)(MYView *))BLOCK{
? ? MYView * view = [[MYView alloc]init];
? ? if (BLOCK) {
? ? ? ? BLOCK(view);
? ? }
? ? return view;
}
-(MYView *(^)(CGRect))viewFrame{
? ? return? ^MYView*(CGRect rect){
? ? ? ? self.frame = rect;
? ? ? ? return self;
? ? };
}
-(MYView *(^)(CGFloat))layerCornerRadious{
? ? return ^MYView*(CGFloat radious){
? ? ? ? self.layer.cornerRadius = radious;
? ? ? ? self.layer.masksToBounds = YES;
? ? ? ? return self;
? ? };
}
-(MYView *(^)(NSString *))ColorString{
? ? return ^MYView* (NSString * colorStr){
? ? ? ? self.backgroundColor = [UIColor redColor];
? ? ? ? return self;
? ? };
}
```
**只需在VC中調(diào)用**
```
[self.view addSubview:[MYView initWith:^(MYView *View) {
? ? ? ? View.viewFrame(CGRectMake(100, 200, 20, 20)).layerCornerRadious(2).ColorString(@"顏色自己設(shè)置");
? ? }]];
```
**完結(jié)** demo地址:https://github.com/IT-iOS-xie/linkProject.git