链式编程
听起来就有种高大上的感觉让人望而却步,但在日常开发中基本都会和它打上交道,典型的例子就是开发布局框架Masonry
的语法结构
make.top.bottom.left.right.equalTo(10).offset(10);
类似于这种通过
点
语法,将代码块像链子一样串联起来,就是链式编程,这样的代码是不是看起来更清晰,写起来更方便了啊
下面我们跟随Masonry
的源码来了解怎么实现链式编程:
一、Masonry 点语法如何实现
make.top中的.top
是MASConstraintMaker的top属性getter方法,返回值是MASConstraint类型,下面我们来看MASConstraint.bottom.left.right
如何实现:
进入MASConstraint
发现left、top、right…等一些属性返回值是它自身类:MASConstraint
,是不是顿时有点明了了,原来make.top.bottom.left.right本质上都是调用属性getter方法
,继续往下看你会发现没这么简单。
接着来看MASConstraint.equalTo(10).offset(10)如何实现,这个时候分开说就说明这里开始不一样了
- 这时的点语法是带着参数的,这个时候
再用getter方法明显是不行了
- 如果是声明了equalTo方法,那就只能用
[]
方式调用不是点语法方式,还是不行啊 - 我们来看看
MASConstraint
是怎么实现:- (MASConstraint * (^)(id attr))equalTo;
,原来是通过带参数的block实现,这样我们就可以使用点语法调用equalTo而且还可以传参,牛批 - 这下是不是就可以知道
.offset(10)
怎么实现了,equalTo(10)返回的是MASConstraint
,类似equalTo的写法可点语法调用可传参:- (MASConstraint * (^)(CGFloat offset))offset;
可以一直套娃下去
二、实现点语法
以UILabel
为例,一般我们我们的写法:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100,100,100,100)];
label.text = @"666";
....
这样一行行写是不是有点麻烦,那能不能像Masonry
那样的使用点语法串联起来呢,下面我们来试试:
1、新建UILabel+Chain分类
// UILabel+Chain.h
@interface UILabel (Chain)
+ (instancetype )my_init;
- (UILabel *(^)(CGFloat x,CGFloat y,CGFloat width,CGFloat height))my_frame;
- (UILabel *(^)(NSString *text))my_text;
- (UILabel *(^)(UIFont *font))my_textFont;
@end
// UILabel+Chain.m
@implementation UILabel (Chain)
+(instancetype)my_init {
return [[[self class] alloc] init];
}
-(UILabel * _Nonnull (^)(CGFloat, CGFloat, CGFloat, CGFloat))my_frame {
return ^(CGFloat x,CGFloat y,CGFloat width,CGFloat height) {
CGRect frame = self.frame;
frame.origin.x = x;
frame.origin.y = y;
frame.size.width = width;
frame.size.height = height;
self.frame = frame;
return self;
};
}
- (UILabel *(^)(NSString *text))my_text
{
return ^(NSString *text)
{
self.text = text;
return self;
};
}
@end
2、使用点语法连续调用
UILabel *label = UILabel.my_init.my_frame(100,100,100,100).my_text(@"666");
与上面的系统方法相比,链式用起来确实方便简洁很多