引言
第三方自动布局框架 Masonry 的出现,是链式语法的鼻祖,也让我们见识到链式语法的魅力!
那么链式语法是如何实现的呢?下面将和大家一起学习。
如下是一段Masonry的布局代码:
[_countDownImg mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(kAutoLayoutWidth(-12.f));
make.centerY.mas_equalTo(self.view.mas_centerY).with.offset(20);
make.width.mas_equalTo(kAutoLayoutWidth(174.f));
}];
我们关注的语法点其实是
make.right.mas_equalTo(kAutoLayoutWidth(-12.f));
make.centerY.mas_equalTo(self.view.mas_centerY).with.offset(20);
make.width.mas_equalTo(kAutoLayoutWidth(174.f));
这句代码中的多个点链式语法
一、make
make 是一个类 MASConstraintMaker创建的对象,MASConstraint 继承 NSObject 。
二、right、top、bottom、width
right、top、bottom、width 均为make对象的公开属性,属于MASConstraint 类。
以right为例,其基本写法为
@interface MASConstraintMaker : NSObject
@property (nonatomic, strong, readonly) MASConstraint *left;
@end
具体实现
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
三、mas_equalTo这个是重点,也是核心所在
这个是mas_equalTo的实现代码
.h中 这里是方法,直接可以用.式语法实现
- (MASConstraint * (^)(id attr))mas_equalTo;
.m中具体实现
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
return ^id(id attribute, NSLayoutRelation relation) {
if ([attribute isKindOfClass:NSArray.class]) {
NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
NSMutableArray *children = NSMutableArray.new;
for (id attr in attribute) {
MASViewConstraint *viewConstraint = [self copy];
viewConstraint.layoutRelation = relation;
viewConstraint.secondViewAttribute = attr;
[children addObject:viewConstraint];
}
MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
compositeConstraint.delegate = self.delegate;
[self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint];
return compositeConstraint;
} else {
NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation");
self.layoutRelation = relation;
self.secondViewAttribute = attribute;
return self;
}
};
}
从这个逻辑来看,这里是利用了一个 <u>block</u> 来实现这个代码和链式语法
这个block 有两个核心特点
- 带返回值 MASConstraint ,返回值就为这个对象本身,这样每次返回值可以继续用其对象属性
- 带入参 id, NSLayoutRelation,边界条件、具体约束的值和约束对象。
链式语法的实现总结
不带入参
- 一、创建一个属性,这个属性属于你需要的类,重写其get方法。
.h文件
@property (nonatomic, strong, readonly) MASConstraint *left;
.m文件
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
- 二、写一个公开方法,返回值为目标类的对象,并实现其方法
.h文件
- (MASConstraint *)left;
.m文件
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
带入参
- 只需要将这个创建一个带返回值和入参的Block即可,可以是属性,也可以是方法。
- (MASConstraint * (^)(id attr))mas_equalTo;
- (MASConstraint * (^)(id))mas_equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
如下是链式语法相关博客
第一篇:链式语法实现分析
第二篇:链式语法使用实战