標籤:地址 cluster sar nsa IV 就是 tab obj 導致
1、前言
開發時常常用數組對資料進行處理,對NSMutableArray進行操作時經常導致程式崩潰,特研究一下NSArray的類簇!涉及__NSPlaceholderArray、__NSArray0、__NSSingleObjectArrayI、__NSArrayI、__NSArrayM相關類。
2、分析NSArray
2.1、建立不可變出租
NSArray *placeholder = [NSArray alloc]; NSArray *arr1 = [placeholder init]; NSArray *arr2 = [placeholder initWithObjects:@0, nil]; NSArray *arr3 = [placeholder initWithObjects:@0, @1, nil]; NSLog(@"arr: %s", object_getClassName([NSArray array])); // arr: __NSArray0 NSLog(@"placeholder: %s", object_getClassName(placeholder)); // placeholder: __NSPlaceholderArray NSLog(@"arr1: %s", object_getClassName(arr1)); // arr1: __NSArray0 NSLog(@"arr2: %s", object_getClassName(arr2)); // arr2: __NSSingleObjectArrayI NSLog(@"arr3: %s", object_getClassName(arr3)); // arr3: __NSArrayI
可以看出 [NSArray array] 等同於[ [NSArray alloc] init],都是空元素類 __NSArray0;
__NSPlaceholderArray:alloc時的對象先統一為這個類對象,不可變數組也是這樣;
__NSArray0:數組init後沒有元素;
__NSSingleObjectArrayI:數組只有一個元素;
__NSArrayI:不可變數組切元素在一個以上;
2.2、分別對arr1、arr2、arr3進行copy和mutableCopy操作:
NSLog(@"arr1: %s", object_getClassName([arr1 copy])); // arr1: __NSArray0 NSLog(@"arr2: %s", object_getClassName([arr2 copy])); // arr2: __NSSingleObjectArrayI NSLog(@"arr3: %s", object_getClassName([arr3 copy])); // arr3: __NSArrayI NSLog(@"================="); NSLog(@"arr1: %s", object_getClassName([arr1 mutableCopy])); // arr1: __NSArrayM NSLog(@"arr2: %s", object_getClassName([arr2 mutableCopy])); // arr2: __NSArrayM NSLog(@"arr3: %s", object_getClassName([arr3 mutableCopy])); // arr3: __NSArrayM
對不可變數組進行copy不會改變類名,但mutableCopy都會變成可變數組;
3、分析NSMutableArray
3.1、建立不可變數組
NSMutableArray *arr = [NSMutableArray alloc]; NSMutableArray *arr1 =[arr init]; NSMutableArray *arr2 = [arr initWithObjects:@0, nil]; NSMutableArray *arr3 = [arr initWithObjects:@0, @1, nil]; NSMutableArray *arr4 = [arr initWithObjects:@0, @1, @2, nil]; NSLog(@"arr: %s", object_getClassName([NSMutableArray array])); // arr: __NSArrayM NSLog(@"placeholder: %s", object_getClassName(arr)); // placeholder: __NSPlaceholderArray NSLog(@"arr1: %s", object_getClassName(arr1)); // arr1: __NSArrayM NSLog(@"arr2: %s", object_getClassName(arr2)); // arr2: __NSArrayM NSLog(@"arr3: %s", object_getClassName(arr3)); // arr3: __NSArrayM
可以看出 [NSMutableArray array] 等同於[ [NSMutableArray alloc] init],都是可變數組類 __NSArrayM;
__NSPlaceholderArray:alloc時的對象先統一為這個類對象;
__NSArrayM:可變數組類;
3.2、分別對arr1、arr2、arr3進行copy和mutableCopy操作:
NSLog(@"arr1: %s", object_getClassName([arr1 copy])); // arr1: __NSArray0 NSLog(@"arr2: %s", object_getClassName([arr2 copy])); // arr2: __NSSingleObjectArrayI NSLog(@"arr3: %s", object_getClassName([arr3 copy])); // arr3: __NSArrayI NSLog(@"================="); NSLog(@"arr1: %s", object_getClassName([arr1 mutableCopy])); // arr1: __NSArrayM NSLog(@"arr2: %s", object_getClassName([arr2 mutableCopy])); // arr2: __NSArrayM NSLog(@"arr3: %s", object_getClassName([arr3 mutableCopy])); // arr3: __NSArrayM
對不可變數組進行copy會改變為對應的不可變數組類名,但mutableCopy不會改變數組;
4、方法持有數組
NSLog(@"==%@",arr3); NSLog(@"arr3: %p", arr3); // arr2: 0x608000014050 [self exchangeMArr:arr3]; NSLog(@"==%@",arr3); NSLog(@"arr3: %p", arr3); // arr2: 0x608000014050
- (void)exchangeMArr:(NSMutableArray *)arr{ NSMutableArray *arr1 = arr; [arr1 removeLastObject]; NSLog(@"arr3: %p", arr1); // arr2: 0x608000014050}
結果:
2018-06-11 14:52:05.902187+0800 ArrTest[5672:265513] ==( 0, 1)2018-06-11 14:52:05.902476+0800 ArrTest[5672:265513] arr3: 0x60400024b1002018-06-11 14:52:05.902828+0800 ArrTest[5672:265513] arr3: 0x60400024b1002018-06-11 14:52:05.903073+0800 ArrTest[5672:265513] ==( 0)2018-06-11 14:52:05.903227+0800 ArrTest[5672:265513] arr3: 0x60400024b100
發現數組的地址不會發生改變,方法裡對arr進行修改後,arr3也會發生改變;
所以如果處理資料時不希望arr3被影響,需要對其進行初始化或者copy就行;
5、__NSPlaceholderArray簡單說明
對NSArray和NSMutableArray進行alloc時產生的都是__NSPlaceholderArray類,只有在init時才會返回是不可變或者可變數組。
這種情況如NSNumber、NSString都是這樣,這就是類蔟(Class clusters)的設計模式。
iOS之NSArray類簇簡介-(copy、mutableCopy導致程式crash)