<br />
......此处省略10000字,作为一个程序员,代码才是文字,是的,开撸。
<br />
1 一步一步来:创建一个对象,并且创建两个方法 eat 和 run
声明方法 实现方法现在我们可以这样子调用方法
Result * res = [[Result alloc] init];
[res eat];
[res run];
<br />
2 如何实现把eat
和 run
写在一行上
[[res eat2] run2];
分析一下,对象方法是由对象调用,当我们调用eat2
之后在调用run2
方法,run2是对象方法,只有对象调用,那是不是我在调用eat2
方法之后返回调用对象就可以了?
<br />
-
效果图
效果图
<br />
- 果不其然,这样子就可以做到了,但是有现在有一个问题啊,调用
eat
方法,到底吃啥我不知道,我也决定不了。我想决定自己吃啥,不能老是让你决定是吧。
<br />
于是我们就可以这样子:吃啥,跑多远外界决定
现在我们就要完成这样子的效果了
[[[res eat3:@"apple"] eat3:@"banana"] run3:100.0];
-
效果图
效果
<br />
下面我们看看block的写法
我们想类似于Masonry那样子去调用怎么写呢?
先来完成一个eat4
和 run4
吧
#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 >
没错,我们换成了 jump
和 play
,来接着看看链式
首先还是一样实现最基本的用法
在项目中,下面的方法我们经常会用
#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大神带入门
alertController.gif简单的介绍一下PQAlertcontroller吧
1 同时支持iphone ,ipad
2 支持链式调用
3 可以实时监听textField输入回调
Demo 附上
用star、喜欢砸死我
网友评论
非block链式
0.017218
0.021022
0.019553
0.018715
0.016700
block链式
0.018646
0.016878
0.018261
0.017682
0.014913