NSUserDefaults.standardUserDefaults() I'd like to understand why after removing an object from a background tread and then adding an object using the same key from main thread, it then becomes impossible to set it again from main. Is this a bug? or does it work as intended?
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
})
You are getting nil
because the instructions are probably executed in the following order
userDefaults.setObject(dataOne, forKey: mykey)
userDefaults.setObject(dataOne, forKey: mykey)
userDefaults.removeObjectForKey(mykey)
print(userDefaults.dataForKey(mike))
First of all, NSUserDefaults
is thread safe. So we can imagine that a writing operation on a given key is performed when there is not another thread that is changing that value.
When this instruction is executed dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { userDefaults.removeObjectForKey(mykey) })
another thread start trying to add the closure to the global queue. While this thread is waiting to access the global queue the execution of your code does continue so this line is (probably) executed
userDefaults.setObject(dataOne, forKey: mike)
This line does lock NSUserDefaults
until dataOne
has been saved.
Next the closure is finally in the main queue and it's ready to be executed so
userDefaults.removeObjectForKey(mike)
And finally the print
print(userDefaults.dataForKey(mykey))
No, it is not a bug. It is very likely that userDefaults.removeObjectForKey(mykey)
was already executed by the DISPATCH_QUEUE_PRIORITY_HIGH
queue right after you'd called setObject(dataOne, forKey: mykey)
the second time so it has already been deleted at the time you want to print it out.
If you change the first dispatch_async
to dispatch_sync
, you'll see the data will be there when you print.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With