初探iOS链式编程思想(仿Masonry)

576 阅读2分钟

Masonry

关于Masonry这个布局库想必大家都不陌生,使用这个库的时候我最感兴趣的是下边这样的代码:

[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.right.top.bottom.equalTo(10);
}];

这里我们只专注于此处的语法,可以无限制的打点掉用,此处我们先来看一下mas_makeConstraints方法的内部实现:

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

我们可以将MASConstraintMaker看作是一个布局制造者,[constraintMaker install]返回的是一个数组NSArray类型,更深的代码我们不深究,我们只看此处数组中的元素MASConstraint,其实一个MASConstraint就相当于一个约束,多个约束结合起来决定一个控件的位置大小,那么我们看我们经常使用的那几个

- (MASConstraint *)left;
- (MASConstraint *)top;
- (MASConstraint *)right;
- (MASConstraint *)bottom;
- (MASConstraint *)width;
- (MASConstraint *)height;
- (MASConstraint * (^)(id attr))equalTo;

此处我们重点看equalTo,因为equalTo是打点调用,所以其返回值必然是一个block,加上equalTo需要传参,所以其定义为

- (MASConstraint * (^)(id attr))equalTo;

由于其返回的block还是MASConstraint本身,所以其还可以继续打点调用,这就是链式编程思想;

  • 注:链式编程思想特定:方法返回值必须要有方法调用者;

链式编程

下边我们照着这个思想,写一个无限加法的例子 我们可以看到Masonry是使用UILabel的对象调用了mas_makeConstraints方法,那么mas_makeConstraints必然是一个类别方法,下边我们照葫芦画瓢创建一个NSObject的类别,方法名字定义为

@interface NSObject (Calculate)
+ (NSInteger)bx_calculate:(void(^)(CalculateManager *manager))block;
@end

@implementation NSObject (Calculate)
+ (NSInteger)bx_calculate:(void(^)(CalculateManager *manager))block{
    CalculateManager *manager = [[CalculateManager alloc] init];
    block(manager);
    return manager.result;
}
@end

此处CalculateManager相当于MASConstraintMaker是个计算管理类,那么我们在CalculateManager类中定一个一个加法

//计算管理
@interface CalculateManager : NSObject
@property (nonatomic, assign) NSInteger result;//计算结果
//加法
- (CalculateManager *(^)(NSInteger value))add;
@end

@implementation CalculateManager
//add的block方法传入参数,返回值需要是CalculateManager才能继续掉用add方法
- (CalculateManager *(^)(NSInteger value))add{
    return ^(NSInteger value){
        _result += value;
        return self;
    };
}

@end

这样就可以实现链式编程中的无限调用了

NSInteger result = [NSObject bx_calculate:^(CalculateManager *manager) {
    manager.add(5).add(10).add(20);
}];
NSLog(@"---->%d",result);

运行结果:

  • 第一次写文章,有什么不对的望指出,谢谢