ZJ_iOS面试iOS Developer程序员

masonry链式赋值的实现原理

2016-11-07  本文已影响221人  风___________

先定个小目标,比如先理解他一句话。。。。

[view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(self.view).sizeOffset(CGSizeMake(100, -50));
    }];

一: make.size//MASConstraintMaker中

- (MASConstraint *)size {
    return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
}
- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs {
    ...............省略...................
    NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count];
    for (MASViewAttribute *a in attributes) {
//注意,children存储的MASViewConstraint实例对象
        [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]];
    }
    MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
    constraint.delegate = self;
    [self.constraints addObject:constraint];
//注意,运行时返回的实际类型为MASCompositeConstraint
    return constraint;
}

二:size.equalTo(self.view)

//.equalTo返回了一个block,定义为:MASConstraint * (^)(id)
- (MASConstraint * (^)(id))equalTo {
    return ^id(id attribute) {
//注意,此处的self是MASCompositeConstraint的实例
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}
//size.equalTo(self.view) 实际上就是调用的MASCompositeConstraint的方法(MASCompositeConstraint.m实现)
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
    return ^id(id attr, NSLayoutRelation relation) {
        for (MASConstraint *constraint in self.childConstraints.copy) {
//注意,constraint实际是MASViewConstraint实例变量
            constraint.equalToWithRelation(attr, relation);
        }
//注意,此处self依旧是MASCompositeConstraint
        return self;
    };
}
//MASViewConstraint中equalToWithRelation(attr, relation);的调用是调用了return的block;
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
    return ^id(id attribute, NSLayoutRelation relation) {
//attribute实际是self.view
        if ([attribute isKindOfClass:NSArray.class]) {
        } else {
//走的这里,到这里已经执行到终点了
            return self;
        }
    };
}

三:.sizeOffset(CGSizeMake(100, -50));

//MASConstraint.m中
- (MASConstraint * (^)(CGSize))sizeOffset {
    return ^id(CGSize offset) {
//注意,调用的MASCompositeConstraint的- (void)setOffset:(CGFloat)offset 方法
        self.sizeOffset = offset;
        return self;
    };
}
//MASCompositeConstraint的- (void)setOffset:(CGFloat)offset 方法
- (void)setOffset:(CGFloat)offset {
    for (MASConstraint *constraint in self.childConstraints) {
//调用的MASViewConstraint的- (void)setOffset:(CGFloat)offset 方法
        constraint.offset = offset;
    }
}
//MASViewConstraint的- (void)setOffset:(CGFloat)offset 方法
- (void)setOffset:(CGFloat)offset {
    self.layoutConstant = offset;
}
//self.layoutConstant就是NSLayoutConstraint了添加约束,就不说啥了
运行时,各个类的穿插的也就上面理解的那样,其余的也大同小异

---------------------------------分割线-------------

链式赋值的实现原理:block的回调获取参数内部使用,所有的set方法返回MASConstraint实例,可以通过'.语法'继续访问

看的略糙~下面几个比较详细,等有时间了仔细看看

Masonry源码分析一
Masonry介绍与使用实践:快速上手Autolayout
追求Masonry

上一篇下一篇

猜你喜欢

热点阅读