美文网首页iOS开发记录IOS
iOS-block的妙用:链式编程(经典应用:Masonry)

iOS-block的妙用:链式编程(经典应用:Masonry)

作者: 狼居胥侯 | 来源:发表于2018-12-02 19:32 被阅读162次

    iOS开发当中有一个很特殊的存在,这个特殊就是block。在OC当中实现某一个功能都是一个响应对象调用一个响应方法,简而言之就是Target-Action。

    以UIButton为例:

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    

    UIButton的事件就是一个响应对象和一个响应方法之间的一一映射。

    与UIButton这种不同,block则不一样,其根本不需要响应对象,如下:

        void (^LogString)(NSString *string) = ^(NSString *string) {
            NSLog(@"这是一个用来打印log的block,需要打印的字符串为:%@", string);
        };
        
        LogString(@"12345");
    

    block的使用无非是以下三个步骤:

    1.block的声明。上述代码中的void (^LogString)(NSString *string就是将void (^)(NSString *string)声明成一个叫LogString的block
    2.block的实现。上述代码中'='后面的便是block的实现,包含了参数与返回值
    3.block的调用。上述代码中的LogString(@"12345")就是对block的调用

    今天小编就来说说block的另外一项应用:链式编程

    说到链式编程最经典的应用便是Masonry了,以下便是Masonry的简单代码:

        [self.nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.leading.top.equalTo(view).priorityHigh();
        }];
    

    其中可以看到对于make这个MASConstraintMaker对象的设置是以一系列的点语法来实现的

    当然,这个leadingtop也是很容易实现的,无非就是以系列的get方法而已。但是后面的equalTo(view)priorityHigh()是什么鬼?我们点进去:

    Masonry源码

    这个时候可以看到equalTo方法的返回值是一个block,而equalTo里面则是一个block的声明,并且将这个block给return了

    如此我们在调用equalTo(view)的时候经历了以下步骤:

    1.调用equalTo方法的对象是MASConstraint,equalTo方法里面声明了一个block和block的实现
    2.MASConstraint对象调用equalTo方法实际上是返回了一个block,这个block的返回值还是MASConstraint对象
    3.步骤2获取到一个block,这个block参数是一个id类型的数据,那么equalTo后面的view参数实际上就作为block的参数了,这也就实现了一个block的调用
    4.因为block的返回值是MASConstraint对象,所以经历步骤3之后的值实际上还是MASConstraint,调用priorityHigh()就又回到了步骤1

    说来说去是不是绕糊涂了?实际上这无非就是block的声明,block的实现与block的实现这三个步骤的另外一种变体。

    接下来我们依据上面总结的Masonry的步骤来对UILabel实现链式编程:

    1.声明一个UILabel的分类,如下:

    UILabel的分类

    2.初始化UILabel的方法声明。在UILabel+Additions.h里声明一个叫label的方法,这个方法没有参数,返回值是一个block,这个block的返回值是一个UILabel对象,block的参数是CGRect的结构体。

    /**
      * 初始化label,此方法是类方法且没有参数
      * 此方法的返回值是一个block
      * 这个block参数为一个CGRect的参数
      * 返回值还是UILabel对象,用来实现链式编程
     */
    + (UILabel *(^)(CGRect frame))label;
    

    3.初始化UILabel的方法实现。在UILabel+Additions.m实现label方法,最主要是实现block,这个在block里实现UILabel的创建,并将这个block返回,如下:

    + (UILabel * _Nonnull (^)(CGRect))label {
        // 声明并实现一个block,并返回
        return ^(CGRect frame) {
            // 根据传过来的frame参数初始化UILabel,并返回
            return [[UILabel alloc] initWithFrame:frame];
        };
    }
    

    同理,设置UILabel的text和textColor也是如此,以下便是代码:
    UILabel+Additions.h进行方法的声明:

    // 对象方法
    - (UILabel *(^)(NSString *title))title;
    - (UILabel *(^)(UIColor *titleColor))titleColor;
    

    UILabel+Additions.m对方法进行实现:

    - (UILabel * _Nonnull (^)(NSString * _Nonnull))title {
        return ^(NSString *title) {
            self.text = title;
            // 返回self就可以了
            return self;
        };
    }
    
    - (UILabel * _Nonnull (^)(UIColor * _Nonnull))titleColor {
        return ^(UIColor *titleColor) {
            self.textColor = titleColor;
            // 返回self就可以了
            return self;
        };
    }
    

    应用代码:

        UILabel *label = UILabel.label(CGRectMake(100, 100, 200, 50)).
                         title(@"链式编程的应用").
                         titleColor([UIColor greenColor]);
        label.backgroundColor = [UIColor redColor];
        [self.view addSubview:label];
    

    效果:


    效果图

    最后打个广告,个人第三方库:
    UDUserDefaultsModel:NSUserDefaults的改进方案
    YIIFMDB:直接操作Model进行增删改查,数学运算等,且sql语句易于管理

    相关文章

      网友评论

      • 74e11af8526c:这样确实是会少写很多代码,也很容易拓展

      本文标题:iOS-block的妙用:链式编程(经典应用:Masonry)

      本文链接:https://www.haomeiwen.com/subject/rvzjcqtx.html