1

我有一个管理我所有列表的 Singleton 对象。我们称它为 ListStore。

ListStore 有一个可变数组,用于存储列表。

@interface ListStore : NSObject
    @property (nonatomic, copy) NSMutableArray *lists; // an array of List objects
end

Lists 有一个可变数组,用于存储事物。

@interface Wanderlist : NSObject <NSCoding, NSCopying>
    @property (nonatomic, copy) NSMutableArray *things; // an array of Thing objects
@end

在任何时候,后台进程都可能通过 ListStore 并循环处理所有 List,而用户可能正在与 List 交互。

为了防止“对象在被枚举时发生变异”类型错误,我这样做:

// all of this is in a background thread
NSArray *newLists = [[ListStore sharedStore] lists] copy];

for (List *list in newLists) {
    // yay, no more crashes, because I'm enumerating over a copied object, so the user
    // can do whatever they want while I'm here

    for(Thing *thing in list.things) {
        // oh crap, my copy and the original object both reference the same list.things,
        // which is why i'm seeing the 'mutation while enumerating" errors still
        ...
    }
}

我最初认为因为我制作了一个副本newLists,所以它的所有成员都会被正确复制。我现在明白情况并非如此:我仍然看到“枚举时对象已变异”错误,但这次它发生在list.things.

我可以在我的设置中使用 NSCopying,这样当我说:

[[ListStore sharedStore] copy];

它打电话copyWithZone:Lists所以我可以再copyWithZone:things吗?

我试图像这样设置它,但copyWithZone:没有被调用。

我知道我可以简单地说NSArray *newList = [list.things copy],但至少我想更好地了解 NSCopying。

4

1 回答 1

3

在提交这个问题之前,我点击了 SO 的相关问题列表中的一个问题,并找到了我的解决方案。

认为发布我的解决方案并没有什么坏处。

而不是这个:

NSArray *newLists = [[ListStore sharedStore] lists] copy];

我必须做:

NSArray *newLists = [[NSArray alloc] initWithArray:[[ListStore sharedStore] lists] copyItems:true];

NSArray 文档

- (id)initWithArray:(NSArray *)array copyItems:(BOOL)flag
flag: 
If YES, each object in array receives a copyWithZone: message to create a copy of the object—objects must conform to the NSCopying protocol. In a managed memory environment, this is instead of the retain message the object would otherwise receive. The object copy is then added to the returned array.

使用 initWithArray:copyItems: 后,它会自动将 copyWithZone 发送到我的所有 List 对象,然后我就可以手动执行 copyWithZone on list.things

于 2013-03-18T23:07:20.933 回答