细嚼慢咽iOS NSArray

2018-03-22  本文已影响48人  David_Do

最近在公司做崩溃防御,参考了safeKit很多源码,利用runtime处理一些我们编程犯得低级错误很有用处,可惜的是作者2年前就弃坑了,其中很多commit都是很有用的。随便这个机会把OC底层知识回顾下,并做下记录和整理。

 NSArray *array = [NSArray alloc] init];
 NSLog(@"array -- 类: %@", [array class]);
 打印的时候发现 array -- 类: __NSArray0
 
 __NSArray0 这个其实是NSArray的子类对象,array常见的子类对象

  只有一个对象的数组  __NSSingleObjectArrayI
  空数组                       __NSArray0
  有对象的数组            __NSArrayI

  可变数组
  NSMutableArray   __NSArrayM
image.png
NSArray *arr0 =  @[];
NSArray *arrAlloc_0 =  [[NSArray alloc] init];
NSLog(@"arr0 -- 类: %@", [arr0 class]);
NSLog(@"arrAlloc_0 -- 类: %@", [arrAlloc_0 class]);

NSArray *arr1 =  [[NSArray alloc] initWithObjects:@"2", nil];
NSArray *arr1_1 =  @[@"1"];
NSLog(@"arr1 -- 类: %@", [arr1 class]);
NSLog(@"arr1_1 -- 类: %@", [arr1_1 class]);

NSArray *arr2 =  @[@"1",@"2"];
NSArray *arr3 =  @[@"1",@"2", @"3"];
NSLog(@"arr2 -- 类: %@", [arr2 class]);
NSLog(@"arr3 -- 类: %@", [arr3 class]);

NSArray *arrPlaceholder =  [NSArray alloc];
NSMutableArray *arrM_placehodler = [NSMutableArray alloc];
NSLog(@"arrPlaceholder -- 类: %@", [arrPlaceholder class]);
NSLog(@"arrM_placehodler -- 类: %@", [arrM_placehodler class]);

NSMutableArray *arrM =  [NSMutableArray array];
NSLog(@"arrM -- 类: %@", [arrM class]);
image.png
因此在用runtime swizzle的时候,一定要区分好。 另外
ios11 以前
objectAtIndex:

ios11 以后
objectAtIndexedSubscript:
 
 分析下这行基础的代码
 NSArray重写了+ (id)allocWithZone:(struct _NSZone *)zone方法,在方法内部,如果调用类为NSArray则直接返回全局变量___immutablePlaceholderArray,如果调用类为NSMUtableArray则直接返回全局变量___mutablePlaceholderArray。
 也就是调用[NSArray alloc]或者[NSMUtableArray alloc]得到的仅仅是两个占位指针,类型为__NSPlaceholderArray.
 
 在调用了alloc的基础上,不论是NSArray或NSMutableArray都必定要继续调用某个initXXX方法,而实际上调用的是__NSPlaceholderArray的initXXX.在这个initXXX方法内部,如果self == ___immutablePlaceholderArray就会重新构造并返回__NSArrayI 对象,如果self == ___mutablePlaceholderArray就会重新构造并返回_NSArrayM对象.
 总结来说,对于NSArray和NSMutableArray,alloc时拿到的仅仅是个占位对象,init后才得到真实的子类对象.

参考文献:
https://www.jianshu.com/p/66f8410c6bbc

后续不断更新..

上一篇下一篇

猜你喜欢

热点阅读