NSArray sortedArrayUsingDescriptors:新复制还是保留?

时间:2013-12-03 15:12:26

标签: ios objective-c arrays

根据NSArray类引用,有四种类型的方法来排序数组:

1- sortedArrayUsingComparator

2- sortedArrayUsingSelector

3- sortedArrayUsingFunction:context

4- sortedArrayUsingDescriptors

前三种方法提到:     新数组包含对接收数组元素的引用,而不是它们的副本。 但对于第四种方法(描述符),它提到:    接收数组的副本按sortDescriptors指定的顺序排序。

但是下面的示例显示了与其他3种方法一样,描述符也保留了原始数组,并且不返回它的新副本:

NSString *last = @"lastName";
NSString *first = @"firstName";

NSMutableArray *array = [NSMutableArray array];
NSDictionary *dict;

NSMutableString *FN1= [NSMutableString stringWithFormat:@"Joe"];
NSMutableString *LN1= [NSMutableString stringWithFormat:@"Smith"];

NSMutableString *FN2= [NSMutableString stringWithFormat:@"Robert"];
NSMutableString *LN2= [NSMutableString stringWithFormat:@"Jones"];

dict = [NSDictionary dictionaryWithObjectsAndKeys: FN1, first, LN1, last, nil];
[array addObject:dict];

dict = [NSDictionary dictionaryWithObjectsAndKeys: FN2, first, LN2, last, nil];
[array addObject:dict];

// array[0].first = "Joe"    ,  array[0].last = "Smith"  
// array[1].first = "Robert" ,  array[1].last = "Jones" 

NSSortDescriptor *lastDescriptor =[[NSSortDescriptor alloc] initWithKey:last
                                                          ascending:YES
                                 selector:@selector(localizedCaseInsensitiveCompare:)];

NSSortDescriptor *firstDescriptor =[[NSSortDescriptor alloc] initWithKey:first
                                                           ascending:YES
                                 selector:@selector(localizedCaseInsensitiveCompare:)];

NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];

NSArray *sortedArray = [array sortedArrayUsingDescriptors:descriptors];

//    array[1] == sortedArray[0] == ("Robert" ,  "Jones")     
//    comparing array entries whether they are same or not:

NSLog(@"  %p  , %p " , [array objectAtIndex:1]  , [sortedArray objectAtIndex:0]  );
//  0x10010c520  ,  0x10010c520

它显示两个数组中的对象相同,

1 个答案:

答案 0 :(得分:2)

“按sortDescriptors指定的顺序排序的接收数组的副本”表示数组对象被复制而不是数组中的元素。文档使用“copy”一词的原因是为了清楚地表明返回的数组与接收者不是同一个数组实例。

数组中的元素永远不会在Cocoa中复制,但initWithArray:copyItems:YES除外,它会将原始数组中的第一级项复制到新数组中。即使这样,这个副本也可以通过调用元素上的copyWithZone:来完成,因此根据数组中的元素应用警告。

请注意,Cocoa是引用计数,因此“深层副本”的概念本身并不是内置的。这也是(部分)为什么cocoa中的数组对象有两种风格(NSArrayNSMutableArray)并且通常是不可变的(NSArray)而不是其他语言中的原因通常不是不可变和可变数组的概念。

请参阅this SO answer了解如何获得NSArray的“深层副本”。