黑魔法:iOS链式编程

链式编程

在使用SDAutoLayout 自动视图布局时就已经发现这种链式编程。通过"." 将属性链接在一起形成如同一条链的编程方法。

 self.totalMoneyCount.sd_layout
.leftEqualToView(self)
.rightEqualToView(self)
.topSpaceToView(self.totalMoney, AutoHeight(15))
.autoHeightRatio(0);

核心实现原理:只要返回是本身这个对象

下列是普通方法的实现,稍候会对两个方法进行改变,形成一个普通的链式。

//Person 类 两个类中均无返回
-(void)goShopping{
    //todo
}

-(void)runing{
    //todo
}

Person *person = [[Person alloc]init];
[person goShopping];
[person runing]; 

普通方法的链式编程

//Person 类 两个类中均返回了本身
-(Person *)goShopping{
    //todo
    return self;
}

-(Person *)runing{
    //todo
    return self;
}

Person *person = [[Person alloc]init];
[[[person goShopping]runing]goShopping];

基本链式,你已经很明白了,但这种方式不美观,如果带参数,你会发现更不美观了,并且如果方法体中参数过长,串起来很难看。

Block形式的链式编程

如果你不太懂Block,那么我建议你先查看iOS之Block

-(Person* (^)(void))goShopping{
Person* (^block)(void) = ^() {
//在调用goShopping()Block时,执行了打印并返回自身,block执行完成,下一个链时,如果想让返回的block再调用对象的方法,那么这个block就需要返回一个对象,即返回block。
        NSLog(@"goShopping");
        return self;
    };
    return block;
}

-(Person* (^)(void))runing{

   Person* (^block)(void) = ^() {
        NSLog(@"runing");
        return self;
    };
    return block;
}

Person *person = [[Person alloc]init];
person.goShopping().runing().goShopping().runing();

到这里,你能很直观看见,block形式的链式比起普通方法的链式形式更美观。
其实很多人都有疑惑,(Person* (^)(void)) runing(^)(void)Person * 这啥意思?其实你可能和我一样,拆开看了,Person* (^)(void) 是一个以Block定义的整体,我第一次看有点懵,后来才看明白。现在我用typedef定义一下。

#import <Foundation/Foundation.h>

@interface Person : NSObject

//注意,typedef block形式要在interface之上才能被自动联想,然后移到interface之下,不然会已找不到Person而报错
typedef Person *(^PersonBlock)(void); 

@property(nonatomic,copy)PersonBlock personBlock;

-(PersonBlock)goShopping;
-(PersonBlock)runing;

@end

#import "Person.h"
@implementation Person

-(PersonBlock)goShopping{
    return ^(void){          
         //todo
         return self;
    };
}

-(PersonBlock)runing{
    return ^(void){
            //todo
        return self;
    };
}
@end

block里处理业务,最后return self 是为了返回本身,继续支持链式。

链式进价

你已经掌握了链式的结构,上面的链式足够你使用了,但你在实际使用时,发现block没有提示带值。完全需要手动,能明显感觉有缺陷。这时候就需要新增几个Block做成属性来替代普通方法。

我将删除无关的代码,包括上面提到过的,实现一个加法运算。

#import <Foundation/Foundation.h>
@interface Person : NSObject
typedef Person* (^Add)(CGFloat value);
// 加法,关于readonly:在调用时,防止出现self.addValue = ^Person *(CGFloat value) {};
@property(nonatomic,copy,readonly)Add addValue;
//计数和
@property(nonatomic,assign)CGFloat sum;
//运算
-(void)runIt;
@end

#import "Person.h"
@interface Person()
@property(nonatomic,copy)Add addValue;
@end
@implementation Person
-(Add)addValue{
    if (!_addValue) {

        //避免循环引用
        __weak typeof(self) weakSelf = self;
        _addValue = ^(CGFloat value){
            weakSelf.sum += value;
            return weakSelf;
        };
    }
    return _addValue;
}
-(void)runIt{
    self.addValue(2).addValue(45).addValue(56).addValue(5);
    NSLog(@"-->%lf",self.sum);
}
@end

链式编程进行分类扩展

因为我用的是Person类进行的加法运算,所以看起来有出处,很奇怪

#import <Foundation/Foundation.h>
#import "Person.h"
@interface NSObject (calculator)
+(CGFloat)Calculate:(void(^)(Person* person)) cal;
@end
@implementation NSObject (calculator)
+(CGFloat)Calculate:(void(^)(Person* person)) cal{
    Person *person = [[Person alloc]init];
    cal(person);
    return person.sum;
}
@end

使用

 CGFloat value = [NSObject Calculate:^(Person *person) {
        person.addValue(12).addValue(56).addValue(1);
    }];

    NSLog(@"->>>>%lf",value);

什么情况下适合链式编程

可以看出,链式编程像是“组合”的一种,不在乎调用的先后顺序(这句话可能不太准确,如果使用链式进行sql语句拼接,还是需要顺序),对于需要额外增加的,只需要新增一个属性。
并且调用方法可以一直调用同一个方法,比如:person.goShopping().goShopping().goShopping无限制。

所以总结:适合动态,可接收不在乎调用先后顺序,次数等动态需求。

至此,你已经掌握了链式编程了。

下一篇:黑魔法:iOS函数式编程

函数式编程和链式编程,微妙的关系


参考文

1. 深入浅出-iOS函数式编程的实现 && 响应式编程概念
2. 几种编程思想在iOS中的实现:(一)链式编程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1 Block机制 (Very Good) Block技巧与底层解析 http://www.jianshu.com...
    Kevin_Junbaozi阅读 9,522评论 3 48
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,273评论 19 139
  • 提到链式编程和函数式编程,最典型的代表是Masonry 比较完美的实现了函数式编程和链式编程。例如 ``` [vi...
    iOS谢先森阅读 3,746评论 0 1
  • 转自Objective-C 链式编程最近看到了链式编程和函数式编程这两个概念,网上查了一些资料,但是发现资料都千篇...
    飞雨2013阅读 4,282评论 1 1
  • 九月十八号七点十三分,哪一天清晨,和往常一样,一宿舍同事都在睡梦中,然而就在这时,不料,莫名的被自己刺耳手机铃声惊...
    罗子僧阅读 3,931评论 6 7

友情链接更多精彩内容