iOS之功能细节iOS 你不知道的新鲜事iOS 开发成长中心

iOS 包看包会的链式编程

2017-07-08  本文已影响546人  Codepgq

<br />
......此处省略10000字,作为一个程序员,代码才是文字,是的,开撸。

<br />

1 一步一步来:创建一个对象,并且创建两个方法 eat 和 run

声明方法 实现方法

现在我们可以这样子调用方法

 Result * res = [[Result alloc] init];
 [res eat];
 [res run];

<br />

2 如何实现把eatrun写在一行上

[[res eat2] run2];

分析一下,对象方法是由对象调用,当我们调用eat2之后在调用run2方法,run2是对象方法,只有对象调用,那是不是我在调用eat2方法之后返回调用对象就可以了?

声明方法 实现方法

<br />

<br />

<br />
于是我们就可以这样子:吃啥,跑多远外界决定

声明方法 实现方法

现在我们就要完成这样子的效果了

[[[res eat3:@"apple"] eat3:@"banana"] run3:100.0];

<br />

下面我们看看block的写法

我们想类似于Masonry那样子去调用怎么写呢?
先来完成一个eat4run4

#pragma mark - 点语法
- (void(^)())eat4;
- (void(^)())run4;

实现

- (void(^)())eat4{
    void(^eat4Block)() = ^(void){
        NSLog(@"eat4");
    };
    return eat4Block;
}
- (void(^)())run4{
    
    return ^(void){
        NSLog(@"run4");
    };
}
ok,看我们这里做了什么,首先我们定义了一个有返回值的方法,返回值是一个没有返回值,没有参数的block,
然后我们在实现文件里面用两种方式去返回了这个block。
然后们就可以在外界这样子调用了
res.eat4();
res.run4();

为什么可以这样调用呢?

block的写法
void (^a)() = ^{
   NSLog(@"调用了block");
};
a();
从上面的代码可以看得出来,调用a()的时候就会执行block里面的代码,在上面我们定义的方法返回一个block
我们可以这样子写:
void (^x)() = [res eat4];
x();
效果是一样的,
.eat4调动的就是get方法,然后我们拿到了一个block,
这个时候我么你直接(),就相当于上面的两步,所以我们可以这样子调用

<br />
然后我们发现,还是不可以链式啊,还是要写两行的,根据上面所述的对象方法的理念,我们可以这样子。

#pragma mark - 点语法 链式 不带参数
- (Result*(^)())eat5;
- (Result*(^)())run5;

实现文件

- (Result*(^)())eat5{
    
    Result *(^eat5Block)() = ^{
        NSLog(@"eat5");
        return self;
    };
    
    return eat5Block;
}
- (Result*(^)())run5{
    return  ^{
        NSLog(@"run 5");
        return self;
    };
}

上面的代码也是两种方式去实现,但是看最后的代码就可以发现,把self 返回出去了,即是当前的对象返回出去了,所以我们就可以这样子写了

res.eat5().eat4();

<br />

#pragma mark - 点语法 链式 带参数
- (Result*(^)(NSString * food))eat6;
- (Result*(^)(float metter))run6;

实现

- (Result*(^)(NSString * food))eat6{
    Result *(^eat6Block)(NSString * food) = ^(NSString * food){
        NSLog(@"eat6 %@",food);
        return self;
    };
    return eat6Block;
}
- (Result*(^)(float metter))run6{
    return ^(float metter){
        NSLog(@"run6 %.2f",metter);
        return self;
    };
}

<br />

<br >

没错,我们换成了 jumpplay ,来接着看看链式

首先还是一样实现最基本的用法
在项目中,下面的方法我们经常会用

#pragma mark - 普通对象方法 - 外界处理 不带参数
- (void)jump:(void(^)())block;
- (void)play:(void(^)())block;

#pragma mark - 普通对象方法 - 外界处理 带参数
- (void)jump2:(void(^)(float metter))block;
- (void)play2:(void(^)(NSString *string))block;

实现

- (void)jump:(void(^)())block{
    if (block) {
        block();
    }
}

- (void)play:(void(^)())block{
    if (block) {
        block();
    }
}

- (void)jump2:(void(^)(float metter))block{
    if (block) {
        block(100);
    }
}
- (void)play2:(void(^)(NSString *string))block{
    if (block) {
        block(@"basketball");
    }
}

调用如下:

 [res jump:^{
     NSLog(@"我来控制输出什么");
 }];
 [res play:^{
     NSLog(@"我来决定玩什么");
 }];
 [res jump2:^(float metter) {
     NSLog(@"被控制要跳%.2f米",metter);
 }];
 [res play2:^(NSString *string) {
     NSLog(@"被要求玩%@",string);
 }];

<br />

上面两种调用方式是不是很常见啊,然后我们结合两种方式一起,再结合链式来玩玩吧。

先来试试没有参数

定义

实现

实现 类是这样子

<br />

带参数

<br />

定义

实现

实现

调用

调用

<br />

上面看了那么久的普通调用方式,现在我们来玩玩block的形式的

首先定义方法

#pragma mark - 点语法 - 传入参数,内部自己处理,返回参数,自己决定做什么
-(void(^)(float metter, void(^)(float metter)))jum5;
-(void(^)(NSString* str, void(^)(NSString* str)))play5;

实现方法

-(void(^)(float metter, void(^)(float metter)))jum5{
    void (^jum5Block)(float metter, void(^)(float metter)) = ^(float metter, void(^neibuBlock)(float metter)){
        if (neibuBlock) {
            neibuBlock(metter);
        }
    };
    return jum5Block;
}
-(void(^)(NSString* str, void(^)(NSString* str)))play5{
    return ^(NSString* str, void(^neibuBlock)(NSString* str)){
        if (neibuBlock) {
            neibuBlock(str);
        }
    };
}

但是我们调用得这个样子调用

res.jum5(123,^(float metter){
    NSLog(@"我自己决定我跳%.2f米",metter);
});
res.play5(@"我给你100块",^(NSString * str){
    NSLog(@"%@,你给我一个篮球",str);
});

效果图

<br />
上面的调用方式明显不爽嘛,换成链式的,其实就是返回一个有返回值且返回值是调用的block
定义

#pragma mark - 点语法 - 传入参数,内部自己处理,返回参数,自己决定做什么 链式
-(Result*(^)(float metter, void(^)(float metter)))jum6;
-(Result*(^)(NSString* str, void(^)(NSString* str)))play6;

实现

-(Result*(^)(float metter, void(^)(float metter)))jum6{
    Result* (^jum6Block)(float metter, void(^)(float metter)) = ^(float metter, void(^neibuBlock)(float metter)){
        if (neibuBlock) {
            neibuBlock(metter * 1.2);
        }
        
        return self;
    };
    return jum6Block;
}
-(Result*(^)(NSString* str, void(^)(NSString* str)))play6{
    return ^(NSString * str, void(^neibuBlock)(NSString * str)){
        
        if (neibuBlock) {
            neibuBlock([NSString stringWithFormat:@"加一个漂亮的签名 %@",str]);
        }
        
        return self;
    };
}

效果图

效果图

到这里为止,了解阶段就完成了,下面要开始实现了一个有用的东西了。

首先我们如果实现一个弹窗,带确定、取消按钮,同时可以输入账户、密码,还不包括处理文字输入情况,我们就需要写这么多代码

UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"牛逼" message:@"💯就是这么强" preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction * action1 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"点击了取消");
    }];
    [alert addAction:action1];
    UIAlertAction * action2 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"点击了确定");
    }];
    [alert addAction:action2];
    
    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        
    }];
    
    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        
    }];
    
    [self presentViewController:alert animated:YES completion:nil];
    

<br />

但是如果我们用链式编程,可以做到实时监听输入情况,外界控制是否密文显示,并且扩张性很强。

PQAlertController *alert= [PQAlertController alertControllerWithTitle:@"难道我这么帅" message:@"帅,不存在的!" preferredStyle:UIAlertControllerStyleAlert];
alert.addAction(@"取消",^{
        NSLog(@"cancel");
    }).addAction(@"确定",^{
        NSLog(@"ok");
    }).addTextInput(@"请输入账户",NO,^(NSString *text,UITextField *textField){
        NSLog(@"%@",text);
    }).addTextInput(@"请输入密码",YES,^(NSString *text,UITextField *textField){
        NSLog(@"%@",text);
    });
[self presentViewController:alert animated:YES completion:nil];
实现类似RAC的text_signal

感谢ZAQ大神带入门


简单的介绍一下PQAlertcontroller吧
1 同时支持iphone ,ipad
2 支持链式调用
3 可以实时监听textField输入回调

alertController.gif

Demo 附上

用star、喜欢砸死我

上一篇下一篇

猜你喜欢

热点阅读