Masonry布局源码精讲(一) -- 链式编程思想

Masonry常用使用方式

	UIView *yellowV = [[UIView alloc] init];
    [yellowV setBackgroundColor:[UIColor yellowColor]];
    [self.view addSubview:yellowV];

    [yellowV mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.right.bottom.equalTo(self.view).with.mas_offset(20);
    }];

需要注意的几个问题:

  1. 添加Masonry布局约束的控件不用设置frame;
  2. 一定要在添加布局之前添加子控件到父控件;
  3. 所有布局问题交给make这个布局管理者执行;

我们仔细观察这一长串代码,在传统Objective-C中我们使用方法都是采用’[]'这种方式,对于setter和getter方法我们采用点语法来使用,但是还有见到能够点一串的,实际上,这个就是我们今天介绍的链式反应编程思想。

make.left.top.right.bottom.equalTo(self.view).with.mas_offset(20);

Masonry就是一个链式编程思想的例子

思考:一般什么情况下可以使用点语法?
通常,类似于UIView声明一个view后,view就可以调用里面的setter和getter方法,一般使用setter和getter方法需要声明成员属性。
如下,就是UIView中定义常用的成员属性,它们对应着各自的setter和getter方法,因此可以使用点语法。

@property(nonatomic) BOOL clipsToBounds;
@property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; 
@property(nonatomic) CGFloat alpha;                      
@property(nonatomic,getter=isOpaque) BOOL opaque;                     
@property(nonatomic) BOOL clearsContextBeforeDrawing;
@property(nonatomic,getter=isHidden) BOOL hidden;
@property(nonatomic) UIViewContentMode contentMode;               

但是,我们介绍的链式编程思想是由Block实现的,如果使用这种编程方式着实搬不上台面,Block很多初次学习的人都会诚惶诚恐,不过,Block的好处真的是无可比拟的。

Block基本思想

首先,我们来看一个Block模型。

- (NSString *(^)(void))block;

这是一个最简单的block的声明了,我们来解读一下

  1. 返回值: NSString;
  2. 传入的参数: void;
  3. Block的名称:block;

我们在方法中声明完block通常怎么调用呢?
很简单,写出它的名称加一对圆括号就可以调用block内容,可以这样理解block,就是将要执行的代码封装到了一个类似于C语言中的函数中,当需要调用时候,使用函数名称直接调用就可以了。

block()

链式编程思想

我们既然可以使用Block名称调用Block,同时,对外,block也可以用做实力化对象,我们不如构造一个不断返回自身的Block出来,不断让自身的类调用自己的Block然后返回自身对象,说起来,肯定有些绕口,看看代码就知道了。

假设我们的类是BlockTest

+ (BlockTest *(^)(void))block1;
- (BlockTest *(^)(void))block2;
- (BlockTest *(^)(void))block3;
- (BlockTest *(^)(void))block4;
- (BlockTest *(^)(void))block5;
- (BlockTest *(^)(void))block6;

这样对外调用效果就如下:

+ (BlockTest * _Nonnull (^)(void))block1{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return [[self alloc] init];
    };
}

- (BlockTest * _Nonnull (^)(void))block2{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return self;
    };
}

- (BlockTest * _Nonnull (^)(void))block3{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return self;
    };
}

- (BlockTest * _Nonnull (^)(void))block4{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return self;
    };
}

- (BlockTest * _Nonnull (^)(void))block5{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return self;
    };
}

- (BlockTest * _Nonnull (^)(void))block6{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(){
        __strong typeof(weakSelf) self = weakSelf;
        return self;
    };
}

这样我们就可以利用链式进行操作了。

BlockTest.block1().block2().block3().block4().block5().block6();

带参数的Block链式操作

我们改写了block6,传入一个字符串参数。

+ (BlockTest *(^)(void))block1;
- (BlockTest *(^)(void))block2;
- (BlockTest *(^)(void))block3;
- (BlockTest *(^)(void))block4;
- (BlockTest *(^)(void))block5;
- (BlockTest *(^)(NSString *))block6;

其余不变,唯独block6中我们输出要传入的内容。

- (BlockTest * _Nonnull (^)(NSString * _Nonnull))block6{
    __weak typeof(self) weakSelf = self;
    return ^BlockTest*(NSString *context){
        __strong typeof(weakSelf) self = weakSelf;
        NSLog(@"%@",context);
        return self;
    };
}
BlockTest.block1().block2().block3().block4().block5().block6(@"I am block6...");

2020-04-26 09:17:33.646799+0800 ReadMasonry[2424:210096] I am block6…

以上就是Block作为链式编程的常用使用方法,对于其核心思想,我们后面几片会通过Masonry框架详细的了解链式编程思想的优点和使用方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值