NSArray类簇

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值