美文网首页iOS Developer程序员
Block高级用法——链式编程简谈

Block高级用法——链式编程简谈

作者: iCode_ | 来源:发表于2016-11-25 15:51 被阅读693次

           我的上一篇文章《iOS程序闪退时的处理一句代码搞定异常拦截》中提到了“链式编程”,可能有读者关于“链式编程”会有些疑问。关于“链式编程”网上也有这方面的文章,这里就简单地谈一下个人的一点愚见,抛砖引玉吧,有不对的地方还请各位看官指正。
           先看段代码

    UIBtn(@"btn1").frame_l(CGRectMake(100, 100, 100, 60))
                  .backgroundColor_l([UIColor redColor])
                  .action(self, @selector(action1:), UIControlEventTouchUpInside)
                  .addToView(self.view);
    

           上面这句代码,将多行代码通过.链接成一句代码,这就是链式编程,也是链式编程的一个优点特点。使用起来很简洁,可读性好。
           怎么才能实现这样的效果呢?看到.我想很多人会想到点语法,在oc里我们首先会想到一个类的实例对象的属性可以被点出来。那么我们怎么才能够一直点下去呢?那就是不断地返回这个实例对象。继续往下想,什么有返回值呢?方法有返回值,但是绝大多数的方法不能用.调用啊,WTF!怎么办。是的,还有Block啊,而且Block还可以声明成类的属性。
           分析到这,那么我们就有了一个基本的思路:在类里的属性用Block,而且Block的返回值是该类的一个实例,然后在这个Block里我们去做一些相应的操作。
           下面我以UIButton为例简单说一下。首先我们创建一个UIButton的Category,当然用继承也可以。也许有的小伙伴找不到创建的地方,上个图。之后的应该都会了。

    接下来上代码(一块来吧,我觉得这样直观一些,后面再分开说),先来.h
    #import <UIKit/UIKit.h>
    
    @interface UIButton (Link)
    
    @property (nonatomic, copy) UIButton *(^frame_l)(CGRect rect);
    @property (nonatomic, copy) UIButton *(^backgroundColor_l)(UIColor *color);
    @property (nonatomic, copy) UIButton *(^addToView)(UIView *view);
    @property (nonatomic, copy) UIButton *(^action)(id target, SEL selector, UIControlEvents events);
    
    UIButton * UIBtn(id name);
    
    @end
    
    • 这里声明了四个Block,分别用来设置frame,backgroundColor,要添加到的父视图,以及Action点击事件
    • 下面的c方法,是用来创建实例对象的,里面的参数相当于对象名,就不用这样[UIButton buttonWithType:UIButtonTypeCustom];创建了,写起来更整洁
    再来.m
    #import "UIButton+Link.h"
    UIButton *button;
    @implementation UIButton (Link)
    -(UIButton *(^)(CGRect))frame_l {
        return ^(CGRect fra) {
            button.frame = fra;
            return button;
        };
    }
    -(void)setFrame_l:(UIButton *(^)(CGRect))frame_l {};
    -(UIButton *(^)(UIColor *))backgroundColor_l {
        return ^(UIColor *color) {
            button.backgroundColor = color;
            return button;
        };
    }
    -(void)setBackgroundColor_l:(UIButton *(^)(UIColor *))backgroundColor_l {};
    -(UIButton *(^)(UIView *))addToView {
        return ^(UIView *view) {
            [view addSubview:button];
            return button;
        };
    }
    -(void)setAddToView:(UIButton *(^)(UIView *))addToView {};
    -(UIButton *(^)(id, SEL, UIControlEvents))action {
        return ^(id target, SEL selector, UIControlEvents events) {
            [button addTarget:target action:selector forControlEvents:events];
            return button;
        };
    }
    -(void)setAction:(UIButton *(^)(id, SEL, UIControlEvents))action {};
    @end
    UIButton * UIBtn(id name) {
        button = [UIButton buttonWithType:UIButtonTypeCustom];
        return button;
    }
    
    • .m主要就是实现属性的getter和setter方法,这里实现setter是为了消除警告
    • c方法中我们对全局的button对象初始化,然后每个属性的getter方法都返回这个对象

           这样我们在使用时,就达到了文章开头那段代码的效果,实现了“链式编程”。可以一直点点点了
           但是现在Xcode对Block的提示不是太友好

    当我们按下回车之后,只会出现addToView不会自动补齐后面的参数

           就说这么多吧,有兴趣的童鞋可以继续添加属性设置。

    最后来个彩蛋,关于Block

    • 在调用Block时我们都会先判断其是否为nil,防止崩溃,通常是这样的
    if (block) {
            block();
        }
    

    其实还可以这样

    !block ? : block();
    

           时间仓促,文章有误之处还请各位留言指正。技术无止境,共同进步,写出优雅的代码,是我不变的追求。

    相关文章

      网友评论

        本文标题:Block高级用法——链式编程简谈

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