autolayout - sizeClass - Masonry - 2

本文深入解析Masonry自动布局库的使用方法,通过实例演示如何利用该库创建和更新视图约束,有效避免循环引用问题,并展示了一种巧妙的链表式布局思路。

参考至:http://www.cocoachina.com/ios/20141219/10702.html

文中提到一个例子:

首先定义的宏:

#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;

乍眼一看,让我这种C基础不好的真是乱了眼,犯了心,将会在别的文章好好研究__typeof这种下划线的什么鬼。

不过这里先理解着,在block里面防止循环引用的__weak处理。而且这么写,代码实在优雅。

结合github上的简介,Masonry提供了主要的三个函数来创建约束,分别是在View+MASAdditions.h中的:

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
分别有什么作用和区别,github上讲得很清楚了。


从参考文章中选取了一个例子如下:

    WS(ws);
    
    UIView* sv = [UIView new];
    sv.backgroundColor = [UIColor blackColor];
    
    [self.view addSubview:sv];
    [sv mas_makeConstraints:^(MASConstraintMaker* make){
    
        make.center.equalTo(ws.view);
        
        make.size.mas_equalTo(CGSizeMake(300, 300));
    
    }];
    
    
    UIView* sv1 = [UIView new];
    sv1.backgroundColor = [UIColor redColor];
    [sv addSubview:sv1];
    
    [sv1 mas_makeConstraints:^(MASConstraintMaker* make){
    
        /** First **/
//        make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
        
        /** Second **/
//        make.top.equalTo(sv).with.offset(10);
//        make.left.equalTo(sv).with.offset(10);
//        make.bottom.equalTo(sv).with.offset(-10);
//        make.right.equalTo(sv).with.offset(-10);

        /** Third **/
        make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
    
    }];

尤其Third方法,虽然可读性很高,但是编程语言的实现上实在太怪异了,  make.top.euqlTo(XX) 这种点调用函数的形式也是很怪,但是在用的前提下,还是挺容易学的。

- (MASConstraint *)with {
    return self;
}

- (MASConstraint *)and {
    return self;
}

其中,and with 函数可是怎么操作都没有做哦,我猜想就是为了增强可读性的。

#pragma mark - composite Attributes

- (MASConstraint *)edges {
    return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom];
}

- (MASConstraint *)size {
    return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
}

- (MASConstraint *)center {
    return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY];
}
而源码的composite Attributes 组合约束更能说明了它将它们“拼凑”的原理。

从上面的例子摘抄一段写的很好的代码:

    UIScrollView *scrollView = [UIScrollView new];
    scrollView.backgroundColor = [UIColor whiteColor];
    [sv addSubview:scrollView];
    [scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(5,5,5,5));
    }];
    UIView *container = [UIView new];
    [scrollView addSubview:container];
    [container mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(scrollView);
        make.width.equalTo(scrollView);
    }];
    int count = 10;
    UIView *lastView = nil;
    for ( int i = 1 ; i <= count ; ++i )
    {
        UIView *subv = [UIView new];
        [container addSubview:subv];
        subv.backgroundColor = [UIColor colorWithHue:( arc4random() % 256 / 256.0 )
                                          saturation:( arc4random() % 128 / 256.0 ) + 0.5
                                          brightness:( arc4random() % 128 / 256.0 ) + 0.5
                                               alpha:1];
        
        [subv mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.and.right.equalTo(container);
            make.height.mas_equalTo(@(20*i));
            
            if ( lastView )
            {
                make.top.mas_equalTo(lastView.mas_bottom);
            }
            else
            {
                make.top.mas_equalTo(container.mas_top);
            }
        }];
        
        lastView = subv;
    }
    [container mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(lastView.mas_bottom);
    }];
结果如下:

每次都会随机颜色,详情看上面的生成随机数,而我觉得除了充分介绍了Masonry的教程,还有一个非常好的地方就是设置了一个lastView,如果我来写一个这么简单的界面,我肯定愣头青地写死或者是写的很复杂,而作者非常巧妙,这里有点像链表,链表的尾端也是大概的处理思想:

UIView *lastView = nil;

---

            if ( lastView )

            {

                make.top.mas_equalTo(lastView.mas_bottom);

            }

            else

            {

                make.top.mas_equalTo(container.mas_top);

            }

---

lastView = subv;

在循环体外面设置一个lastView为nil,如果lastView不为空,将subv的约束置成lastView的底端,如果为空,而是属于container的顶端。

这个思想其实就是: 循环体外 设置bool值 来判断罢了,例如改进的冒泡排序 - 设置一个判断是否Exch的布尔值来优化程序。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值