0

我从斯坦福 iTunes 学习了 Objective-C,我想知道如何在不初始化的情况下将 NSMutableArray 复制到 NSArray。我是说:

这是正确的吗?使用“延迟初始化”。

-(void)copyAnArray:(NSMutableArray*)listOfElements {
    if(privateElementsLists == nil)
        privateElementsLists = [[NSArray alloc] initWithArray:listOfElements copyItems:YES];
    else
        privateElementsLists = listOfElements;
}

这是一个糟糕的设计吗?我想将对象添加到一个类中的可变数组中,然后当我完成将整个 NSMutableArray 复制到 NSArray 时。

还有一个问题:为什么我copyItems:YES在使用initWithArray时必须使用?什么是深拷贝?

4

2 回答 2

2

你可以使用 initWithArray: 将一个可变数组复制到一个新数组中:或者这样:

privateElementsLists = [NSArray arrayWithArray:listOfElements];

那么您正在创建一个新数组,其中每个元素都是与原始数组中的数字相同的对象。如果你写:

privateElementsLists = [NSArray arrayWithArray:listOfElements copyItems:YES];

那么新数组对于每个元素都有原始数组中元素的副本。它们不是同一个对象,而是一个副本。当然,对象必须能够响应复制。

你甚至可以这样做:

privateElementsLists = (NSArray*) listOfElements ;

那么数组就和原来的一模一样了。这里没有新数组。但是当你使用 NSArray 指针类强制转换它时,你可以像使用 NSArray 而不是 NSMutableArray 一样使用它。如您所知,每个 NSMutableArray 都是一个 NSArray(继承类)。

于 2012-04-17T10:59:40.580 回答
2

正如 Joseph DeCarlo 所说,如果您唯一要做的就是在一个地方创建数组以在其他地方使用它,那么您不需要复制NSMutableArray到。NSArray例如,此语句是有效的:

NSArray* newArray = [NSMutableArray array];

或者在代码中:

-(NSArray*)returnAnArray
{
    NSMutableArray* editableArray = [NSMutableArray array];
    [editableArray addObject:[[NSObject alloc] init]]; //an exemplary object added to the array
    return editableArray;
}

然而,这就是说,在某些特定情况下,转换NSMutableArrayNSArray可能不安全,例如,如果原始数组存储在实例变量中。如果同时枚举返回的数组,则在该数组中添加或删除对象可能会导致崩溃。例如:

-(void)createArray
{
    self->editableArray = [NSMutableArray array]; // instance variable: NSMutableArray* editableArray
}

-(void)addObjectToArray
{
    [self->editableArray addObject:[[NSObject alloc] init]];
}

-(NSArray*)getArray
{
    return self->editableArray;
}

-(void)enumerateArray
{
    for(NSObject obj in [self getArray])
    {
        // do something with obj
    }
}

如果与(例如从后台线程)addObjectToArray同时调用,enumerateArray则应用程序将崩溃,因为在枚举时底层数组正在更改。它以 . 的形式返回并不重要NSArray*。在这种情况下,您需要添加以同步多个线程对同一对象的访问,或者按照建议@synchronized复制整个数组。arrayWithArray:但是请注意,文档并没有说明是否arrayWithArray:是线程安全的,所以无论如何我都会@synchronized在调用周围添加arrayWithArray:

于 2012-04-17T12:58:33.233 回答