我的上一篇文章《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();
时间仓促,文章有误之处还请各位留言指正。技术无止境,共同进步,写出优雅的代码,是我不变的追求。
网友评论