iOS 包看包会的链式编程

<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 />

  • 果不其然,这样子就可以做到了,但是有现在有一个问题啊,调用eat方法,到底吃啥我不知道,我也决定不了。我想决定自己吃啥,不能老是让你决定是吧。

<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 />

  • ok,经过上面的代码之后,这个时候还是只能调用吃和跑,不能自己想吃什么就吃什么,想跑多远就跑多远,于是参照对象方法的写法,我们就可以这样子.
#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 />

  • ok 到这里,我们就不在 吃 和 跑 了

<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、喜欢砸死我

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容