Reputation: 20237
I have an app that is configured to use iCloud. I am adding a key/value to the NSUbiquitousKeyValueStore and I can retrieve it as expected across all of my devices. However, if I delete my app's iCloud data from under Settings, I would expect that all of the iCloud data I added to NSUbiquitousKeyValueStore would be deleted as well, but this is not the case. I am able to retrieve all of the data, no matter how long I want for iCloud to sync.
I have gone to developer.icloud.com and watched as my other iCloud data (I am also using Core Data over iCloud) is deleted properly, but their is no folder where NSUbiquitousKeyValueStore keeps its data from what I can tell.
Does anyone know if this is supposed to be deleted? It seems kind of like a "Cloud memory leak" if the user can't delete this.
Upvotes: 8
Views: 3589
Reputation: 590
I resolved the problem by giving users a button in app setting when they can wipe out all the data (including those in NSUbiquitousKeyValueStore
) like this:
func resetAll() {
let keyStore = NSUbiquitousKeyValueStore()
let keys: [String] = keyStore.dictionaryRepresentation.keys.compactMap { $0 }
keys.forEach { key in
keyStore.removeObject(forKey: key)
}
keyStore.synchronize()
}
However, in such a scenario, be aware of not storing any critical data in NSUbiquitousKeyValueStore
, so that a user does not accidentally delete any data they might need in the future or on another device.
Upvotes: 2
Reputation: 977
This will clear it out. #if DEBUG is to prevent you from accidentally shipping this code.
Swift 5.2
#if DEBUG
let allKeys = NSUbiquitousKeyValueStore.default.dictionaryRepresentation.keys
for key in allKeys {
NSUbiquitousKeyValueStore.default.removeObject(forKey: key)
}
#endif
Upvotes: 3
Reputation: 16553
This is a feature not a bug. If you offer all users a one time thing (e.g. everyone starts with 50 free points), you need some way of assuring they don't delete everything and then re-aquire the 50 free points.
Upvotes: 1
Reputation: 3786
It is correct that NSUbiquitousKeyValueStore remains after app deletion. At the moment of deletion, the device does not know whether or not your other devices will still want that shared data.
You would use it to store an in-app purchase status, user details etc. that you wish to be shared between devices, and restored if the app was accidentally deleted (or uninstalled, then reinstalled later)
NSUserDefaults, on the other hand, is data that belongs to the app itself on that device, so deleting the app should delete the data.
Upvotes: 2
Reputation: 122
Deleting iCloud "documents and data" just deletes any documents and CORE data. It does not delete anything in the NSUbiquitousKeyValueStore. My expectation was that it would delete EVERYTHING about the app.
Before adding iCloud support, I was using NSUserDefaults to store small pieces of data for the app. For example, the end user could enter their name and address, and I would store that in NSUserDefaults. It isn't complex data, and I shouldn't need to use core data or a flat file to store it. It's very easy to store it there and it works. If I deleted the app from the phone, that information would be gone, which is what I would expect. When I added iCloud support, I put that into the NSUbiquitousKeyValueStore. However, even if I delete the app, and then delete "documents and data", the end user name and address is STILL there.
I thought I was doing something wrong. After the better part of a day doing research, I found that iCloud key-value storage is supposed to be for "discrete" data and that the "iCloud key-value data store is not something a user would see."
So, while it is perfectly capable of storing non-complex user data that the end user actually does see, that is not the intended use. What I am doing "wrong" is using it for a non-intended use, although it works well for that use.
I'm not certain as to why Apple would not delete EVERYTHING from iCloud. Or at least give the user the ability to.
Upvotes: 3
Reputation: 4436
This is how I do it:
NSUbiquitousKeyValueStore *kvStore = [NSUbiquitousKeyValueStore defaultStore];
NSDictionary *kvd = [kvStore dictionaryRepresentation];
NSArray *arr = [kvd allKeys];
for (int i=0; i < arr.count; i++){
NSString *key = [arr objectAtIndex:i];
[kvStore removeObjectForKey:key];
}
Upvotes: 9