2014-09-23 54 views
2

我有一个对象队列存储到NSUserDefaults。当我需要将对象添加到它,我把下面的方法:iOS 8冻结在更新UserDefaults对象

+ (void)addCodeToQueue:(Code *)code { 
    // Note: userDefaults is a static, initialized variable 

    NSDictionary *codeModel = [self generateCodeModelWith:code]; 

    // Read array from UserDefaults, or create one if nil 
    NSMutableArray *codeQueue = [userDefaults mutableArrayValueForKey:@"CodeQueue"] ? : [[NSMutableArray alloc] init]; 

    // Add code model 
    [codeQueue addObject:codeModel]; 

    // Add/replace array & sync 
    [userDefaults setObject:codeQueue forKey:@"CodeQueue"]; // App freezes here if uncommented 
    [userDefaults synchronize]; 
} 

当我打电话setObject:forKey我的应用程序冻结。如果我为该行添加一个断点,继续运行,它将起作用。如果我不休息,它会冻结。

在我将Xcode更新到版本8并开始使用新的SDK之后,开始发生这种情况。 关于此的任何提示?

回答

14

我在几个应用程序中也遇到了这个问题 - 看起来,通过mutableArrayValueForKey返回可变数组,您可能会卡在互斥锁中。对于我的代码,我换这个方式:

  • 获得一个不变的阵列的NSArray * arrSource = [默认arrayForKey:strKey];
  • 将数据复制到可变数组中: NSMutableArray * arrMutable = [NSMutableArray arrayWithArray:arrSouce];
  • 在arrMutable中设置我的值...
  • 将“modified”数组存储回默认值: [defaults setObject:arrMutable forKey:strKey];

...对我来说,至少,这已经修复了互斥锁问题。

+0

它的工作,谢谢。把它作为一个不可变数组存储起来还是不会有什么区别? – Guilherme 2014-09-24 12:33:40

+0

一旦存储它就不应该存在 - 即使它来自可变对象,您放入NSUserDefaults系统的任何内容都将被永久存储。很高兴它的工作!我正在修复一些旧应用程序,因为同样的原因我们挂了这些应用程序。 – TomRicket 2014-09-25 20:07:49

+0

在我的情况下,它反向工作,我必须保存为NSArray。怪异的事情发生在iOS 8. :-( – Evilripper 2014-09-30 09:49:56

1

经过我的实验,我找到了生成互斥锁所需的最小代码。代码如下: 代码如下。

NSMutableArray *videoArray = [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:VIDEOKEY]; 
[videoArray addObject:item]; 
[[NSUserDefaults standardUserDefaults] setObject:videoArray forKey:VIDEOKEY]; 

有3点要注意:

  1. 如果我删除[videoArray addObject:item];,应用程序会崩溃。
  2. 互斥锁锁定发生在[[NSUserDefaults standardUserDefaults] setObject:videoArray forKey:VIDEOKEY];
  3. 如果我在[videoArray addObject:item];处设置断点,那么互斥锁仍然存在。如果我使用[[NSUserDefaults standardUserDefaults] setObject:videoArray forKey:VIDEOKEY];,则互斥锁将不存在。

可以推断的是,互斥锁是结果通过[NSKeyValueSlowMutableArray addObject:];[NSUserDefaults setObject:forKey:]

顺便说一句,我的解决方案,以解决其计算方法如下:

NSMutableArray *mutableVideoArray; 
NSArray *videoArray = [[NSUserDefaults standardUserDefaults] arrayForKey:VIDEOKEY]; 
if (videoArray) 
    mutableVideoArray = [videoArray mutableCopy]; 
else 
    mutableVideoArray = [NSMutableArray array]; 

if (![mutableVideoArray containsObject:item]) 
{ 
    [mutableVideoArray addObject:item]; 
    [[NSUserDefaults standardUserDefaults] setObject:mutableVideoArray forKey:VIDEOKEY]; 
}