iOS实现类似BitArray的位标记

使用场景

位标记的使用场景很多,主要是用来标记一个变量有没有值。比如在两个对象之间做merge操作的时候,需要知道被merge对象的哪些属性(即对象的property)是否有值,这样才能做到有效的merge。

我们熟悉的JSON转model的第三方库Mantle,它的实现里就有对象的merge,但需要指定merge哪些属性,使用起来比较麻烦,要是借助位标记的话,Mantle的merge就会更加方便,代码也会更简洁。

实现思路

通常位标记会使用long型或long long型来扩展支持,但有时候需要标记的变量个数比较少的话,这样做比较浪费。而在c语言里,char型或8位int型相对long型来说能更好的节省内存空间,所以位标记的实现会依赖char型或8位int型数据类型来实现,下文使用的是8位int型。

如果位标记用来标记一个对象的属性赋值的变化,每个对象的属性个数是不定的,所以位标记实现还应该是动态可变的。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "BitFlag.h"
@interface BitFlag ()
{
int _count;
u_int8_t *flag;
}
@end
@implementation BitFlag
- (instancetype)initWithCount:(NSInteger)count {
if (self = [super init]) {
_count = count;
int num = ceilf(count / 8.0);
int size = num * sizeof(u_int8_t);
flag = malloc(size);
if (flag) {
memset(flag, 0, size);
}
}
return self;
}
- (void)setBitAt:(NSInteger)index {
if (index >= 0 && index < _count) {
u_int8_t f = 1;
flag[index / 8] |= (f << (index % 8));
}
}
- (BOOL)bitAt:(NSInteger)index {
if (index < 0 || index >= _count) {
return NO;
} else {
u_int8_t f = 1;
return ( flag[index/8] & (f << (index % 8)) ) > 0;
}
}
- (void)dealloc {
if (flag) {
free(flag);
flag = NULL;
}
}
@end