ios - ¿Cómo recorrer una jerarquía anidada de NSDictionaries y NSArrays y convertir todo a copias mutables?
objective-c recursion (4)
Tengo un NSDictionary
que contiene instancias de muchos tipos diferentes de objetos ( NSArrays
, NSDictionaries
, NSStrings
, NSNumbers
, etc.). Muchos de los NSDictionaries
y NSStrings
tienen sus propios NSDictionaries
y NSArrays
.
¿Cómo puedo recorrer toda la jerarquía, de arriba a abajo, y convertir TODAS las instancias de NSDictionaries
y NSArrays
en NSMutableDictionaries
y NSMutableArrays
, respectivamente?
¿Hay alguna función fácil de "hacer copias mutables recursivamente" que desconozco? Si no, ¿solo necesito hacer un ciclo y escribir cheque repetidamente? ¿Puedo simplemente reemplazar a medida que avanzo o tengo que reconstruir toda la jerarquía?
Si usó algún método del sistema operativo para crear el diccionario: estos métodos a menudo tienen un parámetro que le permite crear objetos mutables. Por ejemplo, la clase de serializador JSON tiene indicadores para hacer que todos los diccionarios y matrices se puedan modificar, y para hacer que todos los objetos NSString se puedan modificar (NSNumber y NSNull nunca son mutables).
El siguiente método crea una copia mutable anidada (profunda) de matrices, diccionarios y conjuntos anidados. También se puede usar para crear copias mudables de objetos que no son de colección dentro de la jerarquía, como cadenas.
@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
Úselo como
NSDictionary *dict = ...;
NSMutableDictionary *mdict = [dict deepMutableCopy];
(Las claves del diccionario no se copian, solo los valores).
Estoy bastante seguro de haber visto algo así en SO, pero no puedo encontrarlo ahora.
Para el NSDictionary externo, esto creará un down de 1 nivel.
Debe llamar a esto en un método, y continuar para obtener todos los dict
y array
.
NSMutableDictionary *dict=[NSMutableDictionary new];
NSMutableArray *array=[NSMutableArray new];
for(NSDictionary *dict in yourMainDictionary){
if([outerDict[dict] class]==[NSDictionary class]){
[dict setObject:outerDict[dict] forKey:dict];
}
else if([outerDict[dict] class]==[NSArray class]){
array[array.count]=outerDict[dict];
}
}
No compilador marcado. Leer como algoritmo
Si bien la respuesta de Anoop está bien (creo que tampoco la compilé), si su jerarquía de instancias es realmente una lista de propiedades, entonces puede usar NSPropertyListSerialization para deserializar un plist con contenedores mutables y / o nodos hoja.
Esto reduciría a menos líneas de código y probablemente sea más rápido que un descenso manual a través del gráfico de objetos, pero esta solución solo tiene sentido si inicialmente deserializa el plist de alguna parte.