iOS开发当中有一个很特殊的存在,这个特殊就是block。在OC当中实现某一个功能都是一个响应对象调用一个响应方法,简而言之就是Target-Action。
以UIButton为例:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
UIButton的事件就是一个响应对象和一个响应方法之间的一一映射。
与UIButton这种不同,block则不一样,其根本不需要响应对象,如下:
void (^LogString)(NSString *string) = ^(NSString *string) {
NSLog(@"这是一个用来打印log的block,需要打印的字符串为:%@", string);
};
LogString(@"12345");
block的使用无非是以下三个步骤:
1.block的声明。上述代码中的void (^LogString)(NSString *string
就是将void (^)(NSString *string)
声明成一个叫LogString
的block
2.block的实现。上述代码中'='后面的便是block的实现,包含了参数与返回值
3.block的调用。上述代码中的LogString(@"12345")
就是对block的调用
今天小编就来说说block的另外一项应用:链式编程。
说到链式编程最经典的应用便是Masonry了,以下便是Masonry的简单代码:
[self.nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.top.equalTo(view).priorityHigh();
}];
其中可以看到对于make这个MASConstraintMaker对象的设置是以一系列的点语法来实现的。
当然,这个leading和top也是很容易实现的,无非就是以系列的get方法而已。但是后面的equalTo(view)和priorityHigh()是什么鬼?我们点进去:
这个时候可以看到equalTo方法的返回值是一个block,而equalTo里面则是一个block的声明,并且将这个block给return了。
如此我们在调用equalTo(view)的时候经历了以下步骤:
1.调用equalTo方法的对象是MASConstraint,equalTo方法里面声明了一个block和block的实现
2.MASConstraint对象调用equalTo方法实际上是返回了一个block,这个block的返回值还是MASConstraint对象
3.步骤2获取到一个block,这个block参数是一个id类型的数据,那么equalTo后面的view参数实际上就作为block的参数了,这也就实现了一个block的调用
4.因为block的返回值是MASConstraint对象,所以经历步骤3之后的值实际上还是MASConstraint,调用priorityHigh()就又回到了步骤1
说来说去是不是绕糊涂了?实际上这无非就是block的声明,block的实现与block的实现这三个步骤的另外一种变体。
接下来我们依据上面总结的Masonry的步骤来对UILabel实现链式编程:
1.声明一个UILabel的分类,如下:
2.初始化UILabel的方法声明。在UILabel+Additions.h
里声明一个叫label的方法,这个方法没有参数,返回值是一个block,这个block的返回值是一个UILabel对象,block的参数是CGRect的结构体。
/**
* 初始化label,此方法是类方法且没有参数
* 此方法的返回值是一个block
* 这个block参数为一个CGRect的参数
* 返回值还是UILabel对象,用来实现链式编程
*/
+ (UILabel *(^)(CGRect frame))label;
3.初始化UILabel的方法实现。在UILabel+Additions.m
实现label方法,最主要是实现block,这个在block里实现UILabel的创建,并将这个block返回,如下:
+ (UILabel * _Nonnull (^)(CGRect))label {
// 声明并实现一个block,并返回
return ^(CGRect frame) {
// 根据传过来的frame参数初始化UILabel,并返回
return [[UILabel alloc] initWithFrame:frame];
};
}
同理,设置UILabel的text和textColor也是如此,以下便是代码:
在UILabel+Additions.h
进行方法的声明:
// 对象方法
- (UILabel *(^)(NSString *title))title;
- (UILabel *(^)(UIColor *titleColor))titleColor;
在UILabel+Additions.m
对方法进行实现:
- (UILabel * _Nonnull (^)(NSString * _Nonnull))title {
return ^(NSString *title) {
self.text = title;
// 返回self就可以了
return self;
};
}
- (UILabel * _Nonnull (^)(UIColor * _Nonnull))titleColor {
return ^(UIColor *titleColor) {
self.textColor = titleColor;
// 返回self就可以了
return self;
};
}
应用代码:
UILabel *label = UILabel.label(CGRectMake(100, 100, 200, 50)).
title(@"链式编程的应用").
titleColor([UIColor greenColor]);
label.backgroundColor = [UIColor redColor];
[self.view addSubview:label];
效果:
最后打个广告,个人第三方库:
UDUserDefaultsModel:NSUserDefaults的改进方案
YIIFMDB:直接操作Model进行增删改查,数学运算等,且sql语句易于管理