iOS 8在更新UserDefaults对象时冻结

时间:2014-09-23 21:17:52

标签: ios objective-c nsuserdefaults

我有一个存储在NSUserDefaults的对象队列。当我需要向其添加对象时,我调用以下方法:

+ (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之后,这种情况就开始发生了。 有关于此的任何提示吗?

2 个答案:

答案 0 :(得分:15)

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

  • 获取不可变数组作为NSArray * arrSource = [defaults arrayForKey:strKey];
  • 将数据复制到可变数组中: NSMutableArray * arrMutable = [NSMutableArray arrayWithArray:arrSouce];
  • 在arrMutable中设置我的值...
  • 将“已修改”的数组存储回默认值: [defaults setObject:arrMutable forKey:strKey];

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

答案 1 :(得分:1)

在我的实验之后,我找到了生成互斥锁所需的最少代码。 代码如下。

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

有三点需要注意:

  1. 如果我删除[videoArray addObject:item];,则应用会崩溃。
  2. 互斥锁定发生在[[NSUserDefaults standardUserDefaults] setObject:videoArray forKey:VIDEOKEY];
  3. 如果我在[videoArray addObject:item];处创建断点,则互斥锁仍然存在。如果我在[[NSUserDefaults standardUserDefaults] setObject:videoArray forKey:VIDEOKEY];处进行,则互斥锁将不存在。
  4. 可以推断,互斥锁是[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];
    }