NSUserDefaults возвращает изменяемый массив - PullRequest
6 голосов
/ 06 января 2012

Я строю модель для MVC и испытываю аномалию, когда вопреки документации Apple "Значения, возвращаемые из NSUserDefaults, являются неизменяемыми, даже если вы устанавливаете изменяемый объект в качестве значения . ", объект [[NSUserDefaults standardUserDefaults] objectForKey: @" key "] возвращает массив mutable .

Я создал пустое приложение для iOS в Xcode 4D199, чтобы заново создать условие и подтвердить, что оно не отвечает другим факторам в моем проекте.

Я устанавливаю NSMutableArray, как показано:

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

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

и я получаю объект, как показано:

- (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]);
    }
}

Теперь, согласно документации Apple, можно ожидать, что консоль будет отображать только неизменную строку . Но когда я выполняю код, в консоли отображаются следующие строки:

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
)

Итак, мне интересно, есть ли здесь что-то, чего мне не хватает.

Для получения дополнительной информации код, выполняющий тесты, выглядит так:

- (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;
}

Изначально я запустил проект с setupKey , установленным на ДА . После первого запуска я изменил setupKey на NO . Журнал консоли является результатом, в то время как setupKey был установлен на NO . Дайте мне знать, что вы думаете.

Ответы [ 2 ]

2 голосов
/ 06 января 2012

Строго говоря, вы правы.Утверждение «Возвращаемые значения являются неизменяемыми» вводит в заблуждение, потому что это выглядит так, как будто получение изменяемого объекта должно быть невозможным .Тем не менее, оператор должен читаться как «Возвращаемые значения не могут быть гарантированно изменяемыми».Таким образом, даже если вы сохраняете изменяемый массив, когда вы читаете значение обратно, вы получите объект NSArray (который может быть объектом изменяемого потомка класса NSMutableArray, но это не может быть гарантировано и может варьироваться в зависимости от выполнения или зависетьсодержимое массива).

1 голос
/ 02 декабря 2013

isKindOfClass метод не подходит для кластера классов

следующий абзац в документации

Будьте осторожны при использовании этого метода на объектах, представленных кластером классов.Из-за природы кластеров классов возвращаемый объект может не всегда соответствовать ожидаемому типу.Если вы вызываете метод, который возвращает кластер классов, точный тип, возвращаемый методом, является лучшим индикатором того, что вы можете сделать с этим объектом.Например, если метод возвращает указатель на объект NSArray, вы не должны использовать этот метод, чтобы увидеть, является ли массив изменяемым, как показано в следующем коде:

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