1

すべてのリストを管理する Singleton オブジェクトがあります。これを ListStore と呼びます。

ListStore には、リストを格納する可変配列があります。

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

Lists には、Things を格納する可変配列があります。

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

バックグラウンド プロセスはいつでも、ListStore を通過し、すべてのリストをループして処理する可能性がありますが、ユーザーはリストを操作している可能性があります。

「列挙中にオブジェクトが変更された」タイプのエラーを防ぐために、次のようにします。

// 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 を手動で実行できるようになりましたlist.things

于 2013-03-18T23:07:20.933 に答える