NSArray 类簇
类簇(class clusters)是抽象工厂模式在iOS下的一种实现,试图将多个类的实现统一在一起,对外只暴露简单的使用接口,隐藏类的真实实现。iOS中的NSArray,NSDictionary,NSArray以及NSNumber中都使用了这种实现。这里主要看一下数组的大概实现
注: 以下数据使用64位模拟器演示.
NSArray, NSMutableArray
在iOS中,NSArray, NSMutableArray的实现中包含了很多个独立的类,常见的有__NSPlaceholderArray, __NSArray0, __NSSingleObjectArrayI,__NSArrayI, __NSArrayM等
- __NSPlaceholderArray
这是一个中间占位类,在使用alloc方法进行空间开辟之后,未初始化之前的NSArray对象都是这个这个类的子类,而且多次调用alloc方法之后生成的是同一个对象.
for (NSInteger index = 0; index < 5; index++) {
NSArray *array = [NSArray alloc];
NSLog(@"array ---> %@, %p", [array class], array);
NSMutableArray *mutableArray = [NSMutableArray alloc];
NSLog(@"mutableArray ---> %@, %p", [mutableArray class], mutableArray);
}
}
输出结果:
array ---> __NSPlaceholderArray, 0x7fff80198860,mutableArray ---> __NSPlaceholderArray, 0x7fff80198870
array ---> __NSPlaceholderArray, 0x7fff80198860,mutableArray ---> __NSPlaceholderArray, 0x7fff80198870
array ---> __NSPlaceholderArray, 0x7fff80198860,mutableArray ---> __NSPlaceholderArray, 0x7fff80198870
array ---> __NSPlaceholderArray, 0x7fff80198860,mutableArray ---> __NSPlaceholderArray, 0x7fff80198870
array ---> __NSPlaceholderArray, 0x7fff80198860,mutableArray ---> __NSPlaceholderArray, 0x7fff80198870
所以在只是调用alloc方法之后,iOS将生成的数组对象指向了同一个地址空间,这样做也是为了最大限度节约不必要的内存开销.
在这一实现中,系统很有可能使用了静态变量来完成这一过程,猜测的大致实现应该差不多这个样子:
static __NSPlaceholderArray *allocInstanceOfNSArray() {
static ____NSPlaceholderArray *instance;
if(instance) {
instance = [[__NSPlaceholderArray alloc] init];
}
return instance;
}
static __NSPlaceholderArray *allocInstanceOfNSMutableArray() {
static ____NSPlaceholderArray *instance;
if(instance) {
instance = [[__NSPlaceholderArray alloc] init];
}
return instance;
}
+ (id)alloc {
if (self == [NSArray class]) {
return allocInstanceOfNSArray();
}
return allocInstanceOfNSMutableArray();
}
- __NSArray0
如果在NSArray类在调用alloc之后紧接着调用了init方法,那么生成的就是__NSArray0对象了
for (NSInteger index = 0; index < 5; index++) {
NSArray *array = [[NSArray alloc] init];
NSLog(@"array ---> %@, %p", [array class], array);
}
输出结果:
array ---> __NSArray0, 0x7fff8002e6e0
array ---> __NSArray0, 0x7fff8002e6e0
array ---> __NSArray0, 0x7fff8002e6e0
array ---> __NSArray0, 0x7fff8002e6e0
array ---> __NSArray0, 0x7fff8002e6e0
使用字面量生成包含0个元素的数组或者使用allocinit遍历构造器方法,也会生成__NSArray0对象,
NSArray *array001 = @[];
NSLog(@"array001 ---> %@, %p", [array001 class], array001);
NSArray *array002 = @[];
NSLog(@"array002 ---> %@, %p", [array002 class], array002);
输出结果:
array001 ---> __NSArray0, 0x7fff8002e6e0
array002 ---> __NSArray0, 0x7fff8002e6e0
在这里NSMutableArray的初始化开始变得不一样:
for (NSInteger index = 0; index < 5; index++) {
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSLog(@"mutableArray ---> %@, %p", [mutableArray class], mutableArray);
}
输出结果:
mutableArray ---> __NSArrayM, 0x600003b7f120
mutableArray ---> __NSArrayM, 0x600003b3ea30
mutableArray ---> __NSArrayM, 0x600003b752f0
mutableArray ---> __NSArrayM, 0x600003b7f120
mutableArray ---> __NSArrayM, 0x600003b752f0
所以这部分的实现很可能是这个样子的:
// NSArray
__NSArray0 *initInstanceOfNSArray () {
static __NSArray0 *instance ;
if (!instance) {
instance = [[__NSArrayI alloc] init];
}
return instance;
}
- (instancetype)init {
if(self == allocInstanceOfNSArray()) {
return initInstanceOfNSArray;
}
return [[__NSArrayM alloc] init];
}
- __NSSingleObjectArrayI
__NSSingleObjectArrayI 则是针对只有一个元素的数组而单独实现的一个类,
NSArray *singleArray001 = [NSArray arrayWithObject:@"abc"];
NSArray *singleArray002 = @[@"abc"];
NSLog(@"singleArray ---> %@, %p", [singleArray001 class], singleArray001);
NSLog(@"singleArray ---> %@, %p", [singleArray002 class], singleArray002);
输出结果:
singleArray ---> __NSSingleObjectArrayI, 0x6000018c85e0
singleArray ---> __NSSingleObjectArrayI, 0x6000018c85f0