本文的重点:
1 学习并理解如何使用block作为方法的返回值
2 链式编程
3 Masonry
这里不多介绍block的基本用法,感兴趣的朋友可以自己在网上搜索下关于block的资料,已经有很多前辈总结的很好,我这里就不班门弄斧了。
通常的方法
- (void)function {
// do something.
}
这是一个无参数无返回值(返回void)的方法,本文就在这个基础上“添油加醋”.
一、用一个无参数无返回值的block作为方法的返回值
方便大家理解,我们先定义一个名为mBlock,无参数无返回值的block:
typedef void (^mBlock)(void);
然后把它作为方法的返回值:
- (mBlock)function {
mBlock block = ^() {
// do something.
NSLog(@"这是一个block");
};
return block;
}
应为要返回一个mBlock,所以先在方法内部声明一个mBlock类型的block,然后返回。
当然这边也可以直接返回一个无参数无返回值的block,让代码更紧凑一些,这两种写法是一样的。
- (mBlock)function {
return ^() {
// do something.
};
}
接下去就是这个方法的调用了。通常的OC调用方法都是下面这种形式:
[self function];
这里思考一下,我们平时调用属性的setter/getter时,都是使用点语法调用,其本质也是调用的方法啊。所以我们试试看用点语法直接调用function方法:
self.function; // !Property access result unused - getters should not be used for side effects
运行发现,方法可以正常执行,但是Xcode会报一个警告“Property access result unused - getters should not be used for side effects”,可能是因为Xcode检测到了点语法,所以会默认把function当作一个属性,去寻找他的getter方法,但是又没有找到,所以报出一个警告。
更详细的解释可以参考:# Xcode warning “Property access results unused - getters should not be used for side effects”
OK,回到我们的方法调用上,因为function方法调用之后会返回一个block,正常的写法就是用之前声明的mBlock类型接收,然后再调用。
mBlock b = self.function;
b();
下面再这个基础上做一下简化,就变成了:
self.function();
到此,一个完整的用block作为方法的返回值的写法就完成了。下面我们要做的就是怎么让这个过程更容易、编写更高效一点。
二、用一个带参数无返回值的block作为方法的返回值
- (void(^)(NSString *))function {
return ^(NSString *str) {
NSLog(@"我想:%@", str);
};
}
调用:
void (^block)(NSString *) = self.function;
block(@"打球");
简化:
self.function(@"打球");
现在,我们可以通过点语法调用getter方法的形式来调用方法,但是我们知道,getter方法是无法加参数的,通过上面block的形式,实现的结果等同于给getter方法加参数。
思考:在类中,方法的调用者都是‘self’,那如果我们声明一个方法,让他执行完自己的任务后,返回一个‘self’行不行?
- (ViewController *)link {
// do something.
return self;
}
在ViewController.m中,方法执行完毕,返回一个ViewController类,那他不就可以继续调用方法了吗?你可以理解它是一个无返回值的方法,只是它保留了能继续调用其他方法的可能性:
self.link.function(@"打球");
这样就写成了最基础的一个链式编程的方法调用,但是大家可能也感觉到了,声明一个link方法,总感觉很low,能不能让一个方法正常调用,但是又可以继续调用其他的方法呢?
三、用一个带参数带返回值的block作为方法的返回值
上面的link方法因为返回了ViewController本身,所以具备了继续调用其他方法的能力,那假如我们写一个返回值为ViewController的block,又让这个block作为方法的返回值,调用这个block之后返回一个ViewController,不就解决了上面的所有问题吗?
- (ViewController *(^)(NSString *))function {
return ^(NSString *str) {
NSLog(@"我想:%@", str);
return self;
};
}
稍作解释:function方法的第一个return是返回一个block,而第二个return是block的返回值,这里返回的是ViewController类
调用:
self.function(@"打球").function(@"游泳");
执行结果为:
我想:打球
我想:游泳
Masonry
上面的代码,大家有没有感觉有一些熟悉?是不是感觉和Masonry的调用方法有点像?
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(100)
}];
没错,这可能就是链式编程最经典的代表作Masonry的实现方法。当然它要更复杂的多,但是大体的思路就是给UIView扩展方法。
以后有时间我们可以共同探讨Masonry的具体实现,我会争取把自己的理解整理成文章,供大家参考。
上面的内容也是我个人的理解,只停留在表面,也都是些最基础的block用法。有错误还希望大家指正。
网友评论