Block的链式编程

今天讲点iOS开发中如何妙用Block的链式编程来让代码更加清爽。

       

一.在iOS开发中,不带参数的方法是可以通过点语法来调用的。

示例代码:

/** 声明person类 */

@interface Person : NSObject

- (void)study;

@end

/** 实现person类 */

@implementation Person

- (void)study

{

    NSLog(@"学习");

}

@end


/** 调用person类 */

int main(int argc,const char * argv[]) {

    @autoreleasepool {

        Person *p = [[Personalloc] init];

        p.study;  // 这里编译器会报警告,因为你的study并没有返回值,编译器不建议如此调用方法

    }

    return0;

}


二.程序中的地址

我们知道一个指针代表这一个地址,通过这个地址,我们可以对地址里的信息进行访问

其实函数,block,所有非指针数据类型也都是有地址的。而它们的函数名,变量名在底层处理中会变为函数与变量的地址,从而实现了对函数的调用,对变量的访问。

我定义一个函数

void test ()

{

        printf("测试");

}

其实“test”就代表着这段代码的地址


我定义一个block

void (^myBlock)() = ^(){

      NSLog(@"我的block");

};

我们用runtime去rewrite这个block时会发现,在底层中,block会被变为一段函数,并且block中拥有isa指针,这以为着block其实也是一种对象或者结构体(有点跑题了...)


总而言之,我们可以很愚昧的把函数名,block名看做那段源码的地址,从而达到对那段源码的访问。


说了这么多,你可能会想这跟我们今天的主题有什么关系呢?哈哈,原谅我卖这么多关子,这些都是印子,有助于我们理解Block的链式编程。

好了,废话不多说,进入我们今天的主题--如何用block实现链式编程!


三.用Block实现链式编程

首先我先把实现代码写出来

如下:

/** 类的声明 */

@interface Person : NSObject

- (Person *(^)())eat;

- (Person *(^)())sleep;

@end


/** 类的实现 */

@implementation Person

- (Person *(^)())eat

{

    return ^(){

        NSLog(@"吃饭");

        returnself;

    };

}

- (Person *(^)())sleep

{

    return ^(){

        NSLog(@"睡觉");

        returnself;

    };

}

@end


/** 调用 */

int main(int argc,const char * argv[]) {

    @autoreleasepool {

        Person *p = [[Personalloc] init];

        p.eat().sleep().eat().sleep();             //  在这里我们就可以优雅的使用Block的链式编程,怎么样有木有感觉很清爽?

    }

    return0;

}


看了上面的代码,你可能觉得蒙蒙的,没关系我们来一步一步分析它是如何实现的


首先我们看eat方法与sleep方法的声明,我们声明了这两个方法,因为无参,所以我们可以通过点语法直接调用。这两个方法都要求返回一个Person *(^)()类型的block

其次我们看eat方法与sleep方法的实现,我们老老实实的返回了一个Person *(^)()类型的block,OK语法是没有问题的!

最后我们看main函数里的调用 p.eat()  首先我们通过点语法调用了eat方法,这个eat方法返回了一个Person *(^)()类型的block的内存地址,紧接着就是(),我们拿着返回的block给它带了个(),这就调用了我们返回的block,这个block执行完毕后又返回了Person类型的指针,于是我们又可以开开心心的去调用Person的实例方法!这样我们就达到了链式编程的目的。


四.升级版,如何带参!

这里我们讨论,如何能给刚刚的eat和sleep方法带上参数!毕竟没有参数的方法过分局限。

同样,我还是先贴上代码:

/** 声明 */

@interface Person : NSObject

- (Person *(^)(NSString *))eat;

- (Person *(^)(NSString *))sleep;

@end


/** 实现 */

@implementation Person

- (Person *(^)(NSString *))eat

{

    return ^(NSString *foodName){

        NSLog(@"%@", foodName);

        returnself;

    };

}

- (Person *(^)(NSString *))sleep

{

    return ^(NSString *who){

        NSLog(@"%@", who);

        returnself;

    };

}

@end


/** 调用 */

int main(int argc,const char * argv[]) {

    @autoreleasepool {

        Person *p = [[Personalloc] init];

        p.eat(@"大便味的咖喱").sleep(@"最漂亮的女人");   // 有木有一种oc,java傻傻分不清楚的感觉~~

    }

    return0;

}


首先你可能会想,给方法带参不就是eat:(NSString *)foodName嘛,但是这样是不行的,因为oc的语法限制,带上了参数我们便不能通过点语法去调用方法了。

所以我们必须换一种思路,这种思路就是:通过block的参数来给方法传参。


先看声明部分,eat与sleep都要求我们返回一个Person *(^)(NSString *)类型的block,我们再看这个block的类型,一种返回Person指针且传NSString *的block。

我们再看声明部分,我们在方法内的的确确的返回了一个Person *(^)(NSString *)类型的block,OK,语法还是正确的。

最后我们看调用,首先p.eat返回了一个Person *(^)(NSString *)类型的block的block,这个block后面就是一个(),并且这个()内部有一个参数,这不正是调用这个block的正确格式嘛!!!block执行完毕后,又返回了Person 类型的指针,于是乎我们又可以开开心心的调用Person的实例方法了。就这样我们借助了block的参数,达到了给方法传参的目的!


五.结尾总结

Block的链式编程其实就是借助了c语言的语法特性,通过函数的返回值与手写(),从而达到了调用block的目的。

希望大家可以借鉴这个知识点来让自己的code变得更加清爽。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值