背景介绍:
swift提供了一个简单易用的数据组合,元组,英文名叫做tuple。元组内的值可以是任意类型,并不要求是相同类型。一些非常简单的struct的可以用tuple来代替。
tuple的访问可以采用通过名字来获取这些元素的值,也可以通过索引来访问元素的值。非常的灵活、方便。
可惜OC里面不提供这样的语法。在参考了swift语法了,我在这里用数组的方式简单地在OC里实现了一下tuple
实现原理:
1、我用数组作为容器,我将各个值当做数组元素,存入这个数组。访问的时候通过下标就可以访问。
2、那么问题来了:swift里的tuple是允许存入nil指针的,而OC数组里是不允许存入nil指针的。于是我定义了一个NSNullMark类,当存入nil的时候,将nil替换成NSNullMark对象,相反,取数据的时候,遇到NSNullMark对象,换回nil指针
3、那么OC如何创建Tuple呢?UIAlertView类的不定参数的写法,将tuple的创建写成不定参数的函数。在UIAlertView的不定参数函数中,参数是以nil结尾的。而在我们的tuple中,nil是正常支持的值,不能作为参数的结尾。于是我又定义了一个KKEndMark作为参数的结尾。
4、照上面的思路,tuple的创建函数是这样的:
- (instancetype)tupleWithObjects:(id)element, …;
它是这样被调用的:
NSArray* tuple = [NSArray tupleWithObjects: @“第一个参数”, @2, UIView.new, [KKEndMark endMark]];
tuple的访问函数是这样的:
- (id)elementAtIndex:(NSUInteger)index
它是这样被调用的:
NSString* firstValue = [tuple elementAtIndex: 0];
5、以上的调用方式虽然可以正常使用tuple,但是使用起来非常不雅观,调用语法复杂。于是我定义了一些宏来简化调用:
#define OCTupleType NSArray*
#define TUPLE_START [NSArray tupleWithObjects:
#define TUPLE_END , [KKEndMark endMark]];
以上三个宏是这样被使用的:
OCTupleType tuple = TUPLE_START
@4,
@{@“block”:aBlock},
parameter1,
parameter2,
parameter3,
parameter4
TUPLE_END;
参数写在TUPLE_START和TUPLE_END中间,参数之间用逗号隔开。
我又定义了一些宏便于对tuple的访问:
#define TUPLE_GET(________tuple________, ________index________) [(________tuple________) elementAtIndex:(________index________)]
#define TUPLE_GET0(________tuple________) [(________tuple________) elementAtIndex:0]
#define TUPLE_GET1(________tuple________) [(________tuple________) elementAtIndex:1]
#define TUPLE_GET2(________tuple________) [(________tuple________) elementAtIndex:2]
#define TUPLE_GET3(________tuple________) [(________tuple________) elementAtIndex:3]
#define TUPLE_GET4(________tuple________) [(________tuple________) elementAtIndex:4]
#define TUPLE_GET5(________tuple________) [(________tuple________) elementAtIndex:5]
#define TUPLE_GET6(________tuple________) [(________tuple________) elementAtIndex:6]
#define TUPLE_GET7(________tuple________) [(________tuple________) elementAtIndex:7]
#define TUPLE_GET8(________tuple________) [(________tuple________) elementAtIndex:8]
#define TUPLE_GET9(________tuple________) [(________tuple________) elementAtIndex:9]
它们是这样被调用的:
NSDictionary* dic = TUPLE_GET1(tuple);
意思是取出tuple中的索引1
有了这些宏的辅助后,我们的tuple的创建和访问就简单多了。目前的宏的定义最多支持到访问索引9,大部分情况下够用了,再不够可以继续定义
6、最后附上最终实现代码
头文件内容如下:
#import <Foundation/Foundation.h>
#define OCTupleType NSArray<id>*
#define TUPLE_START [NSArray tupleWithObjects:
#define TUPLE_END , [KKEndMark endMark]];
#define TUPLE_GET(________tuple________, ________index________) [(________tuple________) elementAtIndex:(________index________)]
#define TUPLE_GET0(________tuple________) [(________tuple________) elementAtIndex:0]
#define TUPLE_GET1(________tuple________) [(________tuple________) elementAtIndex:1]
#define TUPLE_GET2(________tuple________) [(________tuple________) elementAtIndex:2]
#define TUPLE_GET3(________tuple________) [(________tuple________) elementAtInd