2012-01-06 11 views
6

Estoy construyendo un modelo para MVC y estoy experimentando una anomalía donde al contrario de Apple Documentation"Los valores devueltos de NSUserDefaults son inmutables, incluso si establece un objeto mutable como el valor.", [[NSUserDefaults standardUserDefaults] objectForKey: @ "clave"] está devolviendo una matriz mutable.NSUserDefaults está devolviendo una matriz mutable

Creé una aplicación vacía para iOS en Xcode 4D199 para volver a crear la condición y confirmar que no es responsable de otros factores en mi proyecto.

estoy fijando la NSMutableArray como se muestra:

- (void)setupTest 
{ 
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init]; 
    [mutableArray addObject:@"one"]; 
    [mutableArray addObject:@"two"]; 

    [[NSUserDefaults standardUserDefaults] setObject:mutableArray forKey:@"mutableArray_01"]; 
    [[NSUserDefaults standardUserDefaults] synchronize];  
} 

y, estoy consiguiendo el objeto como se muestra:

- (void)checkTest 
{ 
    NSMutableArray *mutableArrayInCheck = nil; 
    id whatIsThis = [[NSUserDefaults standardUserDefaults] objectForKey:@"mutableArray_01"]; 
    if([whatIsThis isKindOfClass:[NSMutableArray class]]) 
    { 
     NSLog(@"The array is mutable."); 
     mutableArrayInCheck = (NSMutableArray *)whatIsThis; 
    } 
    if([whatIsThis isKindOfClass:[NSArray class]]) 
    { 
     NSLog(@"The array is immutable."); 
    } 
    if ([whatIsThis isMemberOfClass:[NSMutableArray class]]) 
    { 
     NSLog(@"The array is a member of NSMutableArray class"); 
    } 

    if (mutableArrayInCheck) 
    { 
     [mutableArrayInCheck addObject:@"three"]; 
     NSLog([mutableArrayInCheck description]); 
    } 
} 

Ahora, de acuerdo con la documentación de manzana, uno esperaría que la consola solo muestra la línea inmutable . Pero cuando ejecuto el código, las siguientes líneas se muestran en la consola:

2012-01-05 18:47:33.328 Tester_01[78533:f803] The array is mutable. 
2012-01-05 18:47:33.348 Tester_01[78533:f803] The array is immutable. 
2012-01-05 18:47:33.349 Tester_01[78533:f803] (
    one, 
    two, 
    three 
) 

lo tanto, me gustaría saber si hay algo que me falta aquí.

Para obtener información adicional, el código que ejecuta las pruebas es como se muestra:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    BOOL setupKey = NO; 
    if (setupKey) 
    { 
     [self setupTest]; 
    } 
    BOOL checkKey = YES; 
    if (checkKey) 
    { 
     [self checkTest]; 
    } 

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

Inicialmente, me encontré con el proyecto con ClaveKmsDeConfiguración conjunto de . Después de la primera ejecución, cambié el setupKey a NO. El registro de la consola es un resultado, mientras que el setupKey se configuró en NO. Déjame saber lo que piensas.

+1

supongo que sólo quieren decir que debiera No cuente con obtener una matriz mutable. En mis proyectos, a menudo solo asigno un 'NSMutableArray' a un puntero' NSArray', porque hacer '[NSArray arrayWithArray: mutableArray]' solo agregaría overhead, con muy poco beneficio. – mvds

+1

solo una conjetura: reinició la aplicación después de agregar la matriz mutable a los valores predeterminados del usuario y luego de leerla sin configurarla nuevamente. Puedo obtener imágenes, que el objeto permanece igual durante una sesión hasta que se serializó y se escribió en el disco y se volvió a leer. – vikingosegundo

+0

Sí, como expliqué al final de la pregunta, con *** setupKey *** establecido en ** YES **, configuré la matriz mutable la primera vez que ejecuté la aplicación. Después de eso, configuré *** setupKey *** en ** NO **, luego reinicié la aplicación para obtener la salida de la consola descrita anteriormente. – Jin

Respuesta

2

Estrictamente hablando, usted tiene razón. La declaración "Los valores devueltos son inmutables" es confusa, porque esto hace que parezca que obtener un objeto mutable debería ser imposible. Sin embargo, la declaración debe leerse como "No se puede garantizar que los valores devueltos sean mutables". Entonces, incluso si almacena una matriz mutable, cuando lee el valor nuevamente, obtendrá un objeto NSArray (que podría ser un objeto de la clase de descendientes mutable NSMutableArray, pero esto no se puede garantizar y puede variar entre ejecuciones o depender del contenido de matriz).

+0

De hecho. Confiar en este detalle de implementación sería una muy mala idea, ya que también es probable que cambie en cualquier versión futura de OSX o iOS. –

+0

Buen punto. Bueno, la documentación debe reformularlo a cómo lo describió si ese es realmente el caso. De todos modos, en este punto tendré que ser cuidadoso y extraer el contenido para inicializar un nuevo NSMutableArray cada vez que lo obtengo de NSUserDefaults. – Jin

1

isKindOfClass el método no es apropiado para el grupo de clase

el siguiente párrafo se encuentra en la documentación

Tenga cuidado al usar este método en los objetos representados por un grupo de clase. Debido a la naturaleza de los grupos de clases, el objeto que obtienes no siempre es del tipo esperado. Si llama a un método que devuelve un clúster de clase, el tipo exacto devuelto por el método es el mejor indicador de lo que puede hacer con ese objeto.Por ejemplo, si un método devuelve un puntero a un objeto NSArray, no debe utilizar este método para ver si la matriz es mutable, como se muestra en el siguiente código:

// DO NOT DO THIS! 
//if ([myArray isKindOfClass:[NSMutableArray class]]) 
//{ 
// Modify the object 
//} 
Cuestiones relacionadas