iOS 函数式编程(链式编程)
2019-08-17 本文已影响0人
Singularity_Lee
在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。
最为iOS最常见的一个经典的函数式编程代表作Masonry
,就已经展现出了链式编程(通过"."将要执行的代码连续的书写)的好处,通过点语法自由控制所写控件的约束条件
make.centerY.equalTo(self.view).offset(100);
如何理解函数式编程及链式编程
以常用的UITextField为例,每个属性设置前我们需要让UITextField这个对象
去实现其相应的方法,所以我们需要这样一层层的写下去
UITextField *textField=[UITextField new];
textField.frame=CGRectMake(10, 200, 200, 40);
textField.text=@"textField";
textField.placeholder=@"placeholder";
textField.textColor=[UIColor grayColor];
[self.view addSubview:textField];
那换个角度想一下,如果UITextField每个属性设置的时候都把UITextField这个对象也一起返回
了,那我们是不是就可以如同个链条一样.frame.text.placeholder
这样一次性写完我们所需要的所有方法设置了么
UITextField *textField=[UITextField new].func_frame(CGRectMake(10, 200, 200, 40)).func_text(@"textField").func_placeholder(@"placeholder").func_borderStyle(UITextBorderStyleLine).func_clearButtonMode(UITextFieldViewModeWhileEditing);
[self.view addSubview:textField];
而这样的.func_text(@"textField")
通过()
来实现函数的调用,就是函数式编程。经典例子Masonry中make.centerY.equalTo(self.view)
就是如此
而oc中block
则是以()
形式执行方法,那么func_text(@"textField")
代表执行了一个block,而这个block的返回值
如果再是一个对象
的话,那这样的方式不就可以一直链接下去了。
//声明
@interface UITextField (FuncChains)
- (UITextField * (^)(NSString *text))func_text;
//实现
@implementation UITextField (FuncChains)
- (UITextField * (^)(NSString *text))func_text{
return ^id(NSString *text){
self.text=text;
return self;
};
}
如果这样的实现方式还是觉得晦涩,那么则将其看作在func_text中,执行的一个block里赋值给textField的text属性,然后在返回textField这个对象
//实现的同理方法
- (UITextField * (^)(NSString *text))func_text{
UITextField *(^textFieldBlock)(NSString *text)=^(NSString *text){
self.text=text;
return self;
};
return textFieldBlock;
}
最后再回顾下Masonry
中的函数式编程是否就很明确了
如果在执行一个方法后再想执行其他方法,则需要返回这个执行方法的对象,即在执行的block中返回一个对象
/**
* Aliases to corresponding relation methods (for shorthand macros)
* Also needed to aid autocompletion
*/
- (MASConstraint * (^)(id attr))mas_equalTo;
- (MASConstraint * (^)(id))mas_equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
/**
* Modifies the NSLayoutConstraint constant
*/
- (MASConstraint * (^)(CGFloat offset))offset;
- (MASConstraint * (^)(CGFloat))offset {
return ^id(CGFloat offset){
self.offset = offset;
return self;
};
}