8

多くNSDictionaryの異なるタイプのオブジェクト(、、、、など)のインスタンスを含むNSArraysNSDictionariesありNSStringsますNSNumbers。との多くにはNSDictionariesNSStrings独自のネストされたと がNSDictionariesありNSArraysます。

階層全体を上から下にループし、 と のすべてのインスタンスを と にそれぞれ変換するにはどうすればよいNSDictionariesですか?NSArraysNSMutableDictionariesNSMutableArrays

私が知らない簡単な「再帰的に変更可能なコピーを作成する」機能はありますか? そうでない場合は、ループして型チェックを繰り返し行う必要がありますか? 途中で交換できますか、それとも階層全体を再構築する必要がありますか?

4

4 に答える 4

18

次のメソッドは、ネストされた配列、辞書、およびセットのネストされた(深い)可変コピーを作成します。また、文字列など、階層内の非コレクションオブジェクトの可変コピーを作成するために使用することもできます。

@interface NSObject (MyDeepCopy)
-(id)deepMutableCopy;
@end

@implementation  NSObject (MyDeepCopy)
-(id)deepMutableCopy
{
    if ([self isKindOfClass:[NSArray class]]) {
        NSArray *oldArray = (NSArray *)self;
        NSMutableArray *newArray = [NSMutableArray array];
        for (id obj in oldArray) {
            [newArray addObject:[obj deepMutableCopy]];
        }
        return newArray;
    } else if ([self isKindOfClass:[NSDictionary class]]) {
        NSDictionary *oldDict = (NSDictionary *)self;
        NSMutableDictionary *newDict = [NSMutableDictionary dictionary];
        for (id obj in oldDict) {
            [newDict setObject:[oldDict[obj] deepMutableCopy] forKey:obj];
        }
        return newDict;
    } else if ([self isKindOfClass:[NSSet class]]) {
        NSSet *oldSet = (NSSet *)self;
        NSMutableSet *newSet = [NSMutableSet set];
        for (id obj in oldSet) {
            [newSet addObject:[obj deepMutableCopy]];
        }
        return newSet;
#if MAKE_MUTABLE_COPIES_OF_NONCOLLECTION_OBJECTS
    } else if ([self conformsToProtocol:@protocol(NSMutableCopying)]) {
            // e.g. NSString
        return [self mutableCopy];
    } else if ([self conformsToProtocol:@protocol(NSCopying)]) {
            // e.g. NSNumber
        return [self copy];
#endif
    } else {
        return self;
    }
}
@end

次のように使用します

NSDictionary *dict = ...;
NSMutableDictionary *mdict = [dict deepMutableCopy];

(辞書キーはコピーされず、値のみがコピーされます)。

SOでこのようなものを見たことがあると確信していますが、今は見つかりません。

于 2013-03-23T14:58:11.363 に答える
2

Anoop の答えは問題ありませんが (コンパイルもしていないと思います)、インスタンスの階層が実際にプロパティ リストである場合は、NSPropertyListSerializationを使用して可変コンテナーやリーフ ノードを含む plist を逆シリアル化できます。

これにより、コードの行数が減り、オブジェクト グラフを手動で下降するよりも高速になる可能性がありますが、このソリューションは、最初にどこかから plist を逆シリアル化する場合にのみ意味があります。

于 2013-03-23T14:58:45.373 に答える