4

iOS 中的数组

 3 years ago
source link: https://kingcos.me/posts/2020/array_in_ios/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Preface

数组,是我们在开发中经常使用的数据结构,其使用一段连续的内存空间存储。在 Obj-C 中,数组的类型分为 NSArray 不可变数组

Objective-C

NSArray & NSMutableArray

我们都知道,NSArray 是 Obj-C 中的不可变数组,而 NSMutableArray 是 Obj-C 的可变数组。这里我将 Obj-C 中几乎所有可能涉及到的数组对象,进行尝试打印其类别信息:

NSLog(@"%@", [[NSMutableArray alloc] class]);                                 // __NSPlaceholderArray
NSLog(@"%@", [[NSArray alloc] class]);                                        // __NSPlaceholderArray
NSLog(@"%@", [[[NSArray alloc] class] superclass]);                           // NSMutableArray
NSLog(@"%@", [[[[NSArray alloc] class] superclass] superclass]);              // NSArray
NSLog(@"%@", [[[[[NSArray alloc] class] superclass] superclass] superclass]); // NSObject

NSLog(@"%@", [[NSArray array] class]);                                        // __NSArray0
NSLog(@"%@", [[[NSArray alloc] init] class]);                                 // __NSArray0
NSLog(@"%@", [[[[NSArray alloc] init] class] superclass]);                    // NSArray

NSLog(@"%@", [[NSMutableArray array] class]);                                 // __NSArrayM
NSLog(@"%@", [[[NSMutableArray array] class] superclass]);                    // NSMutableArray

NSLog(@"%@", [@[@1] class]);                                                  // __NSSingleObjectArrayI
NSLog(@"%@", [[@[@1] class] superclass]);                                     // NSArray

NSLog(@"%@", [@[@1, @2] class]);                                              // __NSArrayI
NSLog(@"%@", [[@[@1, @2] class] superclass]);                                 // NSArray

NSMutableArray *arr = [NSMutableArray array];
NSLog(@"%@", [arr class]);                                                    // __NSArrayM

[arr addObject:@1];
NSLog(@"%@", [arr class]);                                                    // __NSArrayM

由以上结果,我们可得出下图的继承树:

1

显而易见,NSArrayNSMutableArray 均属于类簇(Class Cluster),Obj-C 中所广泛使用的一种抽象工厂设计模式。这种设计使得类型对外暴露的接口得到统一,隐藏内部的具体实现类。

__NSPlacehodlerArray

__NSPlacehodlerArray 顾名思义即「占位」数组。无论我们要创建 NSArray 还是 NSMutableArray,当调用 alloc 时,均返回了 __NSPlaceholderArray 类型的对象:

NSLog(@"%@", [[NSMutableArray alloc] class]); // __NSPlaceholderArray
NSLog(@"%@", [[NSArray alloc] class]);        // __NSPlaceholderArray

而每次使用的 __NSPlaceholderArray

id arr1 = [NSArray alloc];
id arr2 = [NSArray alloc];
id arr3 = [NSArray alloc];
id arr4 = [NSArray alloc];
id arr5 = [NSArray alloc];

id marr1 = [NSMutableArray alloc];
id marr2 = [NSMutableArray alloc];
id marr3 = [NSMutableArray alloc];
id marr4 = [NSMutableArray alloc];
id marr5 = [NSMutableArray alloc];

// 0x7fff90a905b8 - 0x7fff90a905b8 - 0x7fff90a905b8 - 0x7fff90a905b8 - 0x7fff90a905b8
NSLog(@"%p - %p - %p - %p - %p", arr1, arr2, arr3, arr4, arr5);
// 0x7fff90a905c8 - 0x7fff90a905c8 - 0x7fff90a905c8 - 0x7fff90a905c8 - 0x7fff90a905c8
NSLog(@"%p - %p - %p - %p - %p", marr1, marr2, marr3, marr4, marr5);

// 0x7fff90a905c8 - 0x7fff90a905b8 == 16

那么问题来了,__NSPlaceholderArray 内部是如何区分将要初始化的数组类型呢?

For historical reasons, alloc invokes allocWithZone:.

根据官方文档中的提示,alloc 方法由于历史原因,内部仍然调用了 allocWithZone:.。我们通过 LLDB breakpoint set --name "+[NSArray allocWithZone:]" 打个断点

CoreFoundation`+[NSArray allocWithZone:]:
->  0x7fff38ecb971 <+0>:   pushq  %rbp
    ...
    0x7fff38ecb9e8 <+119>: jmp    0x7fff38ecba0c            ; __NSArrayImmutablePlaceholder
    ...
    0x7fff38ecba02 <+145>: jmp    0x7fff38ee4a8d            ; __NSArrayMutablePlaceholder

CoreFoundation`__NSArrayImmutablePlaceholder:
->  0x7fff38ecba0c <+0>: leaq   0x57bc4ba5(%rip), %rax    ; ___immutablePlaceholderArray
    0x7fff38ecba13 <+7>: retq

CoreFoundation`__NSArrayMutablePlaceholder:
->  0x7fff38ee4a8d <+0>: leaq   0x57babb34(%rip), %rax    ; ___mutablePlaceholderArray
    0x7fff38ee4a94 <+7>: retq

Swift

Array

Reference


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK