NSmutableArray 的实现原理机制

Posted 旅途

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NSmutableArray 的实现原理机制相关的知识,希望对你有一定的参考价值。

古老的C数组:

优点:查询速度很快,直接通过下表找到对应的值
缺点:修改、删除数据很慢,需要移动基于所有的其他的元素
 
P160
P155
插入和删除一个元素,需要移动后面所有的元素
改进的目标:实现快速增加,删除

NSMutableArray的内部数据结构如下:

P158


几个主要变量:
offset: 有效数据起始位置偏移量
size: 实际占用的内存大小
used: 数组的实际的有效数据个数
*list: 实际内存的起始地址
P156
 

删除元素

[arr removeObjecAtIndex:0];
[arr removeObjecAtIndex:0];

 

执行两次 remove的实现:
P159

仅仅修改 offset即可,内存完全不需要移动。
那么问题来了,移走的这个元素的内存怎么释放的呢?
回到OBJC的引用计数,offset移走,这个对象的引用计数减一,对象引用计数到0之后,由autoreleasepool释放。over

插入元素

[arr insertObjec:@"test"atIndex:0];

 

执行insertObjec的实现:
 
P154
 
如果buff的size还够用,不需要扩展buff,数据会在buff的末端添加进去,此时offset由0变成size-1,used+1.over
循环buff的牛逼之处就在于此,无需移动内存,实现插入元素。

删除元素

[arr removeObjecAtIndex:3];

 

实现:
 
P157
 
删除头尾元素直接修改offset或者used即可
但是如果删除中间元素,就避免不了移动其他元素,不过NSArray会选择更少移动的那一边移动数据。
所以我们在实际使用过程中应该尽量避免这么做。

tip:

NSMutableArray *array = [NSMutableArray array];
 
for (int i = 0; i < 10000; i++) {
    [array addObject:[NSObject new]];
}
[array removeAllObjects];
 
数组移除所有元素,buff并不会被立即清空
输出size的结果:
1
Size: 14336 
如果你在利用NSArray保存大量数据的时候,就要注意了。remove之后,记得置为nil,才能立刻释放掉buff.
总结:
1.数组越界奔溃: index > _used+offset 或 index < 0。
2.如果想要内存记录释放,remove之后记得置nil.或者直接置nil.猜想Array的dealloc的方法会自动给所有元素发release消息。

 

以上是关于NSmutableArray 的实现原理机制的主要内容,如果未能解决你的问题,请参考以下文章

按字典键的值对包含 NSMutableDictionary 的 NSMutableArray 进行排序

Instrument使用

NSmutableArray添加数据添加失败打印NULL - 没有初始化/初始化写错

谓词不敏感搜索两个字符串数组

iOS tableview和 Collection复用机制

iOS 高效的分页加载(TableViewCollectionView)