I have an iOS app with a share extension. I am trying to share data between them using NSUserDefaults and App Groups but, while I can write into the NSUD object, read it, and synchronize()
without error, reading in the extension always results in nil
.
I have an app group, the literal string "group.net.foo.bar" for which both the app & extension have configured under Capabilities -> App Groups. This string is in a constants struct in my app:
struct Forum {
static let APP_GROUP = "group.net.foo.bar"
static let AUTH_KEY = "AUTH_KEY"
}
In the main app I create a UserDefaults object and write to it:
fileprivate lazy var userDefaults: UserDefaults = {
let defaults = UserDefaults()
defaults.addSuite(named: Forum.APP_GROUP)
return defaults
}()
// later
userDefaults.set(apiKey, forKey: Forum.AUTH_KEY)
userDefaults.synchronize()
Creating a new NSUD object after that synchronize()
and retrieving the AUTH_KEY works. In the extension, I create an NSUD and try to retrieve the value, to no avail:
private lazy var userDefaults: UserDefaults = {
let defaults = UserDefaults()
defaults.addSuite(named: Forum.APP_GROUP)
return defaults
}()
// later
private func getApiKey() -> String? {
return userDefaults.string(forKey: Forum.AUTH_KEY)
}
// returns nil
In all of my reading of the Apple docs and depressingly-similar questions here on Stack Overflow I can't divine what I've done incorrectly.
Xcode Version 8.0 (8A218a), also tested with Xcode 8.1 Beta 2. Same behavior on simulator andy my iPhone 6s running iOS 10.
It appears the limit is the maximum file size for iOS (logically), which is currently 4GB: https://discussions.apple.com/thread/1763096?tstart=0. The precise size of the data is circumscribed by the compiler types (NSData, NSString, etc.) or the files in your asset bundle.
Thread SafetyThe UserDefaults class is thread-safe.
There isn't a way to check whether an object within NSUserDefaults is empty or not. However, you can check whether a value for particular key is nil or not.
Saving to NSUserDefaults : Basically, all you have to do is load NSUserDefaults, and then tell it to save a value to a specific key. Here is a simple example of writing an integer to NSUserDefaults: NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
Not sure if defaults.addSuite(named: ...)
does the same as UserDefaults(suiteName: ...)
. In my app I use appGroups this way and it works as expected:
// write
if let userDefaults = UserDefaults(suiteName: appGroupName) {
userDefaults.set("---" as AnyObject, forKey: "distance")
userDefaults.set("---" as AnyObject, forKey: "altitude")
...
userDefaults.synchronize()
}
// read
if let userDefaults = UserDefaults(suiteName: appGroupName) {
self.distanceLabel.text = userDefaults.string(forKey: "distance")
self.altitudeLabel.text = userDefaults.string(forKey: "altitude")
}
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