Drew Stephens Drew Stephens - 1 month ago 6
iOS Question

Why doesn't NSUserDefaults work between my app & share extension?

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.

Answer

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")
}
Comments