iOS 函数式编程(链式编程)

2019-08-17  本文已影响0人  Singularity_Lee

在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合。
最为iOS最常见的一个经典的函数式编程代表作Masonry,就已经展现出了链式编程(通过"."将要执行的代码连续的书写)的好处,通过点语法自由控制所写控件的约束条件

make.centerY.equalTo(self.view).offset(100);

基础控件函数式简易写法 Demo


如何理解函数式编程及链式编程

以常用的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;
}

基础控件函数式简易写法 Demo


最后再回顾下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;
    };
}
上一篇 下一篇

猜你喜欢

热点阅读