在iOS中,Masonry自动布局库
是典型的链式与函数式编程的集中体现。基于函数式编程范式
的思想,包装组装对应的功能的同时链式串联组装
,整体实现功能组装实现上顺畅自然,方便阅读,更体现了策略者模式
的设计优势。
为了达到链式调用的目的,例如(obj.add().muti()
)的操作,这其中包含以下的重要信息:
- 点语法的使用
- 链式操作的实现
- 链式对象实例以及方法的包装操作
实现点语法调用操作
首先说第一点,在OC中点语法的操作有两种:
1.Blcok
调用
2.通过内置属性取值调用(getter
)
所以我们可以依据第一点实现一个点语法操作,如下:
//声明一个block
@property (nonatomic, copy) void * (^addPushDes)(NSString *parameter);
@property (nonatomic, copy) GCDemoObj * (^addPushID)(NSString *parameter);
//取当前属性
- (void)testBlock{
GCDemoObj *demoObj = [GCDemoObj new];
demoObj.addPushDes(@“des”);
demoObj.addPushID(@“ID”);
}
//声明的实现
- (void (^)(NSString *parameter))addPushDes{
return ^(NSString *parameter){
//包装操作的实现在这里写
}
}
- (void (^)(NSString *parameter))addPushID{
return ^(NSString *parameter){
//包装操作的实现在这里写
}
}
实现链式调用能力
demoObj.addPushDes(@“”);
这行代码实际上做了两件事情:
1.取Block
2.调用Block
完成点语法之后,接下来就是如何去将整个操作串联起来,如何去实现一个链式操作组装呢?其实很好理解,就是在调用Block之后,将Block中函数的返回值设置为当前的类对象
即可,因为返回对象本身之后,它就能接着进行自身其他的方法调用了,所以Block这一块的返回值是实现链式操作
的关键。所以经过改造之后的结果如下:
//声明一个block
@property (nonatomic, copy) GCDemoObj * (^addPushDes)(NSString *parameter);
@property (nonatomic, copy) GCDemoObj * (^addPushID)(NSString *parameter);
//取当前属性
- (void)testBlock{
GCDemoObj *demoObj = [GCDemoObj new];
demoObj.addPushDes(@"des").addPushID(@"ID");
}
//声明的实现
- (GCDemoObj * (^)(NSString *parameter))addPushDes{
return ^GCDemoObj * (NSString *parameter){
//包装操作的实现在这里写
return self;
}
}
- (GCDemoObj * (^)(NSString *parameter))addPushID{
return ^GCDemoObj * (NSString *parameter){
//包装操作的实现在这里写
return self;
}
}
实现链式调用的封装操作(Masonry的链式内容方法包装)
以上基本实现了链式操作的功能了,但是并不够完美,通常想要用这个对象还是需要将对象进行一次实例操作,并且实例之后链式调用脱离了当前的实例,能不能两步封成一步操作,在实例的同时设置包装属性设置,完成最终的效果,所以这样的实例操作就来了,在进行一次方法改造:
+ (instancetype)makeDemoObj:(void (^) (GCDemoObj *))settingBlock{
GCDemoObj *obj = [GCDemoObj new];
settingBlock(obj); //这一步很关键,实现方法设置内容
return obj;
}
最后
所以实现以上三步更改之后,基本上就实现了一个简单的函数式与链式调用方案,这里为了去除setter
属性的操作(屏蔽setter
提示操作),可以将包装的属性内容设置为readonly
。以下是三步变换之后的操作代码。
//声明一个block
@property (nonatomic, copy, readonly) GCDemoObj * (^addPushDes)(NSString *parameter);
@property (nonatomic, copy, readonly) GCDemoObj * (^addPushID)(NSString *parameter);
+ (instancetype)makeDemoObj:(void (^) (GCDemoObj *make))settingBlock{
GCDemoObj *obj = [GCDemoObj new];
settingBlock(obj); //这一步很关键,实现方法设置内容
return obj;
}
//取当前属性
- (void)testBlock{
GCDemoObj *demoObj = [GCDemoObj new];
demoObj.addPushDes(@"des").addPushID(@"ID");
}
//声明的实现
- (GCDemoObj * (^)(NSString *parameter))addPushDes{
return ^GCDemoObj * (NSString *parameter){
//包装操作的实现在这里写
return self;
}
}
- (GCDemoObj * (^)(NSString *parameter))addPushID{
return ^GCDemoObj * (NSString *parameter){
//包装操作的实现在这里写
return self;
}
}
使用的时候就与Masonry的使用方式一样了,如下:
+ (void)useDemo{
[GCDemoObj makeDemoObj:^(GCDemoObj *make){
make.addPushDes(@"des").addPushID(@"456");
}];
}
网友评论