我們經常使用的開源框架 Masonry 就是使用這樣的編程思想,Masonry是一個OC開發中,非常好用的自動布局框架,通過點語法來進行多個操作
代碼示例:
[greenView makeConstraints:^(MASConstraintMaker *make) {
make.top.greaterThanOrEqualTo(superview.top).offset(padding);
make.left.equalTo(superview.left).offset(padding);
make.bottom.equalTo(blueView.top).offset(-padding);
make.right.equalTo(redView.left).offset(-padding);
}];
這種將多個操作(多行代碼)通過點號(.)鏈接在一起成為一句代碼,使代碼可讀性提高,我們稱之為鏈式編程。
鏈式編程特點:方法的返回值是block,block必須返回對象本身(返回block時,block所在的方法調用者對象)block的參數是需要操作的值。
下面通過一個簡單的示例解讀鏈式編程,展示鏈式編程的魅力。
1. 創建Person類
person.h 頭文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (Person* (^)())eat;
- (Person* (^)())go;
- (Person* (^)(NSString *))study;
@end
person.m 實現文件
#import "Person.h"
@implementation Person
//該函數返回一個 Person* (^)() 類型的 block 變量,當該類對象調用 block() 會打印eat 并且返回該當前類對象
- (Person* (^)())eat
{
//block變量保存的代碼段
Person* (^block)() = ^(){
NSLog(@"eat");
//返回當前類對象
return self;
};
//返回block變量
return block;
}
- (Person* (^)())go
{
return ^Person *(){
NSLog(@"go go go");
return self;
};
}
//該函數返回一個 Person* (^)(NSString *) 類型的 block 變量
- (Person* (^)(NSString *))study
{
Person* (^block)(NSString *) = ^(NSString *yyy){
NSLog(@"%@ study",yyy);
return self;
};
return block;
}
@end
2. 調用示例:
Person *person = [Person new];
person.eat().go().study(@"good good");
3. 輸出結果:
2016-02-26 14:37:06.179 Day2016-02-26-函數編程[2579:87725] eat 2016-02-26 14:37:06.180 Day2016-02-26-函數編程[2579:87725] go go go 2016-02-26 14:37:06.180 Day2016-02-26-函數編程[2579:87725] good good study
4. 分析:
分解以上調用的代碼
第一步:執行 person.eat 返回對應的eatBlock變量。
Person* (^eatBlock)() = person.eat;
第二步:執行eatBlock,此時返回當前person對象。
person = eatBlock();
第三步:執行 person.go 返回對應的goBlock變量。
Person* (^goBlock)() = person.go;
第四步:執行goBlock,此時返回當前person對象。
person = goBlock();
第五步:執行 person.study 返回對應的studyBlock變量。
Person* (^studyBlock)(NSString *) = person.study;
第六步:執行studyBlock,此時返回當前person對象。
person = studyBlock(@"good good");
按照分解步驟調用實現:
Person *person = [Person new];
Person* (^eatBlock)() = person.eat;
person = eatBlock();
Person* (^goBlock)() = person.go;
person = goBlock();
Person* (^studyBlock)(NSString *) = person.study;
person = studyBlock(@"good good");
輸出結果:
2016-02-26 15:40:34.371 Day2016-02-26-函數編程[2948:107876] eat 2016-02-26 15:40:34.371 Day2016-02-26-函數編程[2948:107876] go go go 2016-02-26 15:40:34.372 Day2016-02-26-函數編程[2948:107876] good good study
這樣就可以一直鏈接下去吧!實現了我們想要的目標!
5. 函數式編程總結
如果想再去調用別的方法,那么就需要返回一個對象;
如果想用()去執行,那么需要返回一個block;
如果想讓返回的block再調用對象的方法,那么這個block就需要返回一個對象(即返回值為一個對象的block)