在swift中提供了包括map、filter、reduce等十分简洁优秀的高阶函数供我们对数组数据进行操作,同样情况下,遍历一个数组并求和在使用oc(不使用kvc)和swift的环境下的代码是这样的:
#pragma mark - OC code
NSArray numbers = @[@10, @15, @99, @66, @25];
NSInteger totalNumber = 0;
for (NSNumber number in numbers) {
totalNumber += number.integerValue;
}
#pragma mark - swift code
let numbers = [10, 15, 99, 66, 25];
let totalNumber = numbers.reduce(0, { $0+$1 })
无论是代码量还是简洁性,此时的oc都比不上swift。那么接下来就要通过神奇的block来为oc添加这些高阶函数的实现。为此我们需要新建一个NSArray的分类扩展,命名为 NSArray+HigherFunc
NSArray+HigherFunc.h 内容如下:
#import <Foundation/Foundation.h>
//数组元素转换
typedef id(^HigherFuncItemMap)(id item);
typedef NSArray*(^HigherFuncArrayMap)(HigherFuncItemMap itemMap);
//数组元素筛选
typedef BOOL(^HigherFuncItemFilter)(id item);
typedef NSArray*(^HigherFuncArrayFilter)(HigherFuncItemFilter itemFilter);
@interface NSArray (HigherFunc)
@property (nonatomic, copy, readonly) HigherFuncArrayMap map;
@property (nonatomic, copy, readonly) HigherFuncArrayFilter filter;
@end
实现链式编程,函数调用的前提是具有返回对象。因此我使用了typedef声明了几个不同类型的block。虽然本质上HigherFuncArrayMap和HigherFuncArrayFilter两个block是一样的,但是为了区分它们的功能,还是建议这么做。
NSArray+HigherFunc.m 内容如下:
#import "NSArray+HigherFunc.h"
@implementation NSArray (HigherFunc)
- (HigherFuncArrayMap)map {
HigherFuncArrayMap map = ^NSArray*(HigherFuncItemMap itemMap) {
NSMutableArray *items = @[].mutableCopy;
for (id item in self) {
[items addObject:itemMap(item)];
}
return items;
};
return map;
}
- (HigherFuncArrayFilter)filter {
HigherFuncArrayFilter filter = ^NSArray*(HigherFuncItemFilter itemFilter) {
NSMutableArray *items = @[].mutableCopy;
for (id item in self) {
if (itemFilter(item)) {
[items addObject:item];
}
}
return items;
};
return filter;
}
#pragma mark -
#pragma mark 重写set方法防止外部修改实现 method
- (void)setMap:(HigherFuncArrayMap)map {}
- (void)setFilter:(HigherFuncArrayFilter)filter {}
@end
我们通过重写setter方法保证block不会被外部修改实现,并且在getter中遍历数组的元素并调用传入的执行代码来实现map和filter等功能。
使用
NSMutableArray *array = @[].mutableCopy;
[array addObject:@{@"name":@"jack",@"code":@1}];
[array addObject:@{@"name":@"judy",@"code":@2}];
[array addObject:@{@"name":@"judy",@"code":@3}];
[array addObject:@{@"name":@"mike",@"code":@4}];
NSArray *arr = array.map(^id(id item) {
NSString *dic = item;
NSString *name = [dic valueForKey:@"name"];
return @{@"name": name};
});
NSLog(@">>>map:%@",arr);
arr = array.filter(^BOOL(id item) {
NSDictionary *dic = item;
NSInteger code = [[dic objectForKey:@"code"] integerValue];
return code > 2;
});
NSLog(@">>>filter:%@",arr);
//运行结果
2018-08-31 13:00:46.759468+0800 BlockDemo[542:125803] >>>map:(
{
name = jack;
},
{
name = judy;
},
{
name = judy;
},
{
name = mike;
}
)
2018-08-31 13:00:46.759611+0800 BlockDemo[542:125803] >>>filter:(
{
code = 3;
name = judy;
},
{
code = 4;
name = mike;
}
)
由于语法上的限制,虽然这样的调用跟swift原生的调用对比起来还是复杂了,但通过block让oc实现了函数链式调用的代码看起来也清爽了很多
附上源代码地址:
https://github.com/guodunsong/HigherFuncDemo
上一篇:KVC的使用技巧
网友评论