简介
函数式编程
特点:通过block实现,block做返回值
//在分类方法
@interface NSString (Append)
- (NSString *(^)(NSString *str))appendString;
- (NSString *(^)(void))haveNoParam;
- (void(^)(NSString *str))haveNoReturn;
@end
@implementation NSString (Append)
- (NSString *(^)(NSString *str))appendString {
return ^(NSString *str) {
return [self stringByAppendingString:str];
};
}
- (NSString *(^)(void))haveNoParam {
return ^{
return self;
};
}
- (void(^)(NSString *str))haveNoReturn {
return ^(NSString *str) {
NSLog(@"%@", str);
};
}
@end
// 需要调用的地方
- (void)funcCode {
NSString *str = @"函数式";
NSLog(@"%@", str.appendString(@"test"));
NSLog(@"%@", str.haveNoParam());
str.haveNoReturn(@"no return");
}
这里原理是使用了OC中的getter方法,只不过此处返回的是一个block,而非我们平时使用的对象,test字符串就是调用block时的传参了
这个方法的缺点也就暴露出来了,只能调用一次,不能连续使用点语法
链式编程
特点:使用点语法将方法串联起来,可读性更强,返回值是self
//在分类方法
@interface NSString (Append)
- (NSString *)log;
@end
@implementation NSString (Append)
- (NSString *)log {
NSLog(@"%@", self);
return self;
}
@end
// 需要调用的地方
- (void)chainCode {
NSString *str = @"链式";
str.log.log.log;
}
这里应该很好理解,使用它的返回值,即self继续调用下一个方法,但由于没有接收者,会有warning,也可以使用自己接收一下~
- (void)chainCode {
NSString *str = @"链式";
str = str.log.log.log;
}
函数式+链式
函数式+链式编程最经典的使用就是masonry了
// 使用方法
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(20));
make.height.equalTo(@(20));
make.left.equalTo(self.view).offset(20);
make.top.equalTo(self.view).offset(20);
}];
// 源码
- (MASConstraint *)width {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
}
- (MASConstraint * (^)(id))equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
- (MASConstraint * (^)(CGFloat))offset {
return ^id(CGFloat offset){
self.offset = offset;
return self;
};
}
从源码可以看出,make对象调用width时返回了MASConstraint实例对象(使用了上面链式编程的思想),它可以继续调用equalTo方法,返回值block可以传参(使用了函数式编程思想),block的返回值又是MASConstraint实例对象(两者合二为一),让其可以继续调用后面的方法,优雅!