NSUserDefaults 从其他线程中删除和设置对象



NSUserDefaults.standardUserDefaults()我想了解为什么从后台胎面中删除对象然后使用主线程中的相同键添加对象后,无法从主线程再次设置它。这是一个错误吗?还是按预期工作?

    let mykey = "nsDataKeyOne"
    let stringUno:NSString = "................."
    let dataOne = stringUno.dataUsingEncoding(NSUTF8StringEncoding)!
    let stringDos:NSString = "000000000000000000"
    let dataTwo = stringDos.dataUsingEncoding(NSUTF8StringEncoding)!
    let userDefaults = NSUserDefaults.standardUserDefaults()

    userDefaults.setObject(dataOne, forKey: mykey)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
        userDefaults.removeObjectForKey(mykey)
    })
    userDefaults.setObject(dataOne, forKey: mykey)
    print(userDefaults.dataForKey(mykey))  // print nil, why?

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
        userDefaults.setObject(dataTwo, forKey: mykey)
        print(userDefaults.dataForKey(mykey)) // there is data
    })

简答

您正在nil,因为指令可能按以下顺序执行

userDefaults.setObject(dataOne, forKey: mykey)
userDefaults.setObject(dataOne, forKey: mykey)
userDefaults.removeObjectForKey(mykey)
print(userDefaults.dataForKey(mike))

原因

首先,NSUserDefaults是线程安全的。因此,我们可以想象,当没有另一个线程正在更改该值时,对给定键执行写入操作。

执行此指令时dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {userDefaults.removeObjectForKey(mykey)})

另一个线程开始尝试将闭包添加到全局队列。当此线程等待访问全局队列时,代码的执行确实会继续,因此此行(可能)已执行

userDefaults.setObject(dataOne, forKey: mike)

此行会锁定NSUserDefaults,直到保存dataOne

接下来,闭包终于在主队列中,可以执行

userDefaults.removeObjectForKey(mike)

最后是印刷品

print(userDefaults.dataForKey(mykey))

不,这不是错误。很可能在您第二次调用setObject(dataOne, forKey: mykey)后,userDefaults.removeObjectForKey(mykey)已经被DISPATCH_QUEUE_PRIORITY_HIGH队列执行,因此在您要打印它时它已被删除。

如果将第一个dispatch_async更改为 dispatch_sync ,则在打印时会看到数据将在那里。

最新更新