Reputation: 9367
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
})
Upvotes: 6
Views: 4409
Reputation: 59506
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))
Upvotes: 6
Reputation: 52163
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.
Upvotes: 2