如何调整NSMutableDictionary的内存布局以适应存储?
摘要:有关NSDictionary的内存布局,可以参看《NSDictionary 的内存布局》。 1 类图 和《NSDictionary 的内存布局》中的类图相比较,本章类图多了2个新成员: __NSDictionaryM __NSCFDicti
有关NSDictionary的内存布局,可以参看《NSDictionary 的内存布局》。
1 类图
和《NSDictionary 的内存布局》中的类图相比较,本章类图多了2个新成员:
__NSDictionaryM
__NSCFDictionary
2 __NSDictionaryM
通过下面的方式,可以创建__NSDictionaryM:
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{"kaaa": @"aaa"}];
从Xcode的控制台输出可以看到:
(lldb) po [dictM class]
__NSDictionaryM
2.1 初始化
__NSDictionaryM的初始化流程和__NSDictionaryI类似。
当调用+[NSMutableDictionary dictionaryWithDictionary:]方法时,最终会调用到-[__NSPlaceholderDictionary initWithObjects:forKeys:count]方法。
-[__NSPlaceholderDictionary initWithObjects:forKeys:count]方法在NSDictionary部分已经介绍过。
这里重新贴出与__NSDictionaryM相关的伪代码:
// -[__NSPlaceholderDictionary initWithObjects:forKeys:count]
@interface __NSPlaceholderDictionary
...
@end
@implementation __NSPlaceholderDictionary
- (instancetype)initWithObjects:(ObjectType const[])objects forKeys:(ObjectTpye const[])keys count:(NSUInteger)count {
...
label:
if (self == ___immutablePlaceholderDictionary) {
...
} else if (self == ___mutablePlaceholderDictionary) {
// 创建 __NSDictionaryM
return __NSDictionaryM_new(keys, objecs, count, 3);
}
error "创建出错"
}
从伪代码可以看到,最终会调用到__NSDictionaryM_new方法。
下面就来看看__NSDictionaryM_new的内部实现。
和创建__NSDictionaryI对象一样,__NSDictionaryM_new一开始也需要遍历__NSDictionaryCapacities数组。
遍历的目的,同样是为了找到一个index,这个index对应的capacity大于或者等于count。
BOOL found = NO;
NSInteger index = 0;
for (; index < 40; index++) {
if (__NSDictionaryCapacity[i] >= count) {
found = YES;
break;
}
}
if (!found) {
error "不能创建 NSDictionary";
}
从上面伪代码可以看到,创建__NSDictionaryI最多遍历64项,而这里只遍历40项。
有了index,就可以从__NSDictionarySizes数组中,得到要创建的字典的size。
