NSUserDefaults正在返回一个可变数组。

6
我正在构建一个MVC模型,并且遇到了异常情况,与Apple Documentation相反,尽管您设置了可变对象作为值,“NSUserDefaults返回的值是不可变的。”,但[[NSUserDefaults standardUserDefaults] objectForKey:@"key"]返回一个可变数组。
我在Xcode 4D199中创建了一个空的iOS应用程序,以重新创建条件并确认它不受我的项目中的其他因素的影响。
我设置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]);
    }
}

现在,根据苹果的文档,人们预期控制台只会显示不可变行。但是当我执行代码时,控制台会显示以下行:

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设置为YES的项目。第一次运行后,我将setupKey更改为NO。控制台日志是在setupKey设置为NO时生成的结果。请告诉我您的想法。


1
我想他们的意思只是说你不应该指望得到一个可变数组。在我的项目中,我经常将NSMutableArray分配给NSArray指针,因为使用[NSArray arrayWithArray:mutableArray]只会增加开销,而几乎没有什么好处。 - mvds
1
只是猜测:在将可变数组添加到用户默认设置后,您是否重新启动了应用程序,然后在不再设置它的情况下读取它。我可以想象,在一次会话期间,对象保持不变,直到被序列化并写入磁盘并再次读取。 - vikingosegundo
是的,就像我在问题的结尾所解释的那样,当 setupKey 设置为 YES 时,我第一次运行应用程序时设置了可变数组。之后,我将 setupKey 设置为 NO,然后重新启动应用程序以获取上述控制台输出。 - Jin
2个回答

2

严格来说,您是正确的。语句“返回的值是不可变的”很令人困惑,因为这使得似乎获取可变对象应该是不可能的。然而,应该将该语句理解为“不能保证返回的值是可变的”。因此,即使您存储了一个可变数组,在读取值时,您将获得一个NSArray对象(该对象可能是可变后代类NSMutableArray的对象,但不能保证并且可能在运行时或取决于数组内容而有所不同)。


确实。依赖于这个实现细节是一个非常糟糕的想法,因为它也很可能在任何未来的OSX或iOS版本中发生变化。 - Catfish_Man
好的观点。如果真是这样的话,文档应该重新阐述一下你所描述的内容。无论如何,在这个时候,我只能小心谨慎地提取内容,每当我从NSUserDefaults获取它时,就初始化一个新的NSMutableArray。 - Jin

1

isKindOfClass方法不适用于类簇。

下一段是文档内容:

在使用此方法时,对于由类簇表示的对象要小心。由于类簇的特性,您获取的对象可能并不总是预期的类型。如果调用返回类群的方法,则方法返回的确切类型是指示您可以对该对象执行哪些操作的最佳指标。例如,如果方法返回一个指向NSArray对象的指针,则不应使用此方法查看数组是否可变,如下面的代码所示:

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

但是你能做什么呢?如何判断某个东西是否可变? - Motti Shneor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接