美文网首页selector
曲线理解iOS链式编程(用Block作为方法的返回值)

曲线理解iOS链式编程(用Block作为方法的返回值)

作者: YYYYYY25 | 来源:发表于2018-05-12 17:59 被阅读45次

本文的重点:

1 学习并理解如何使用block作为方法的返回值

2 链式编程

3 Masonry

这里不多介绍block的基本用法,感兴趣的朋友可以自己在网上搜索下关于block的资料,已经有很多前辈总结的很好,我这里就不班门弄斧了。


通常的方法

- (void)function {
    // do something.
}

这是一个无参数无返回值(返回void)的方法,本文就在这个基础上“添油加醋”.

一、用一个无参数无返回值的block作为方法的返回值

方便大家理解,我们先定义一个名为mBlock,无参数无返回值的block:

typedef void (^mBlock)(void);

然后把它作为方法的返回值:

- (mBlock)function {
    mBlock block = ^() {
        // do something.
        NSLog(@"这是一个block");
    };
    return block;
}

应为要返回一个mBlock,所以先在方法内部声明一个mBlock类型的block,然后返回。
当然这边也可以直接返回一个无参数无返回值的block,让代码更紧凑一些,这两种写法是一样的。

- (mBlock)function {
    return ^() {
      // do something.
    };
}

接下去就是这个方法的调用了。通常的OC调用方法都是下面这种形式:

[self function];

这里思考一下,我们平时调用属性的setter/getter时,都是使用点语法调用,其本质也是调用的方法啊。所以我们试试看用点语法直接调用function方法:

self.function;  // !Property access result unused - getters should not be used for side effects

运行发现,方法可以正常执行,但是Xcode会报一个警告“Property access result unused - getters should not be used for side effects”,可能是因为Xcode检测到了点语法,所以会默认把function当作一个属性,去寻找他的getter方法,但是又没有找到,所以报出一个警告。

更详细的解释可以参考:# Xcode warning “Property access results unused - getters should not be used for side effects”

OK,回到我们的方法调用上,因为function方法调用之后会返回一个block,正常的写法就是用之前声明的mBlock类型接收,然后再调用。

mBlock b = self.function;
b();

下面再这个基础上做一下简化,就变成了:

self.function();

到此,一个完整的用block作为方法的返回值的写法就完成了。下面我们要做的就是怎么让这个过程更容易、编写更高效一点。

二、用一个带参数无返回值的block作为方法的返回值

- (void(^)(NSString *))function {
    return ^(NSString *str) {
        NSLog(@"我想:%@", str);
    };
}

调用:

void (^block)(NSString *) = self.function;
block(@"打球");

简化:

self.function(@"打球");

现在,我们可以通过点语法调用getter方法的形式来调用方法,但是我们知道,getter方法是无法加参数的,通过上面block的形式,实现的结果等同于给getter方法加参数。

思考:在类中,方法的调用者都是‘self’,那如果我们声明一个方法,让他执行完自己的任务后,返回一个‘self’行不行?

- (ViewController *)link {
    // do something.
    return self;
}

在ViewController.m中,方法执行完毕,返回一个ViewController类,那他不就可以继续调用方法了吗?你可以理解它是一个无返回值的方法,只是它保留了能继续调用其他方法的可能性:

self.link.function(@"打球");

这样就写成了最基础的一个链式编程的方法调用,但是大家可能也感觉到了,声明一个link方法,总感觉很low,能不能让一个方法正常调用,但是又可以继续调用其他的方法呢?

三、用一个带参数带返回值的block作为方法的返回值

上面的link方法因为返回了ViewController本身,所以具备了继续调用其他方法的能力,那假如我们写一个返回值为ViewController的block,又让这个block作为方法的返回值,调用这个block之后返回一个ViewController,不就解决了上面的所有问题吗?

- (ViewController *(^)(NSString *))function {
    return ^(NSString *str) {
        NSLog(@"我想:%@", str);
        return self;
    };
}

稍作解释:function方法的第一个return是返回一个block,而第二个return是block的返回值,这里返回的是ViewController类
调用:

self.function(@"打球").function(@"游泳");

执行结果为:

我想:打球
我想:游泳

Masonry

上面的代码,大家有没有感觉有一些熟悉?是不是感觉和Masonry的调用方法有点像?

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(self).offset(100)
}];

没错,这可能就是链式编程最经典的代表作Masonry的实现方法。当然它要更复杂的多,但是大体的思路就是给UIView扩展方法。


以后有时间我们可以共同探讨Masonry的具体实现,我会争取把自己的理解整理成文章,供大家参考。
上面的内容也是我个人的理解,只停留在表面,也都是些最基础的block用法。有错误还希望大家指正。

相关文章

网友评论

    本文标题:曲线理解iOS链式编程(用Block作为方法的返回值)

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