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

2

5

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.

Intussusception answered 11/10, 2016 at 16:43 Comment(0)
C
9

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")
}
Chinese answered 11/10, 2016 at 16:53 Comment(4)
Bravo, that's it. Any idea what defaults.addSuite(named: ...) is for?Intussusception
Glad to help you. As stated above, I'm not sure. The documentation is somewhat confusion here.Chinese
Indeed—I think I got tripped up because all of the current examples I found were with ObjC or Swift 2.3 which used initWithSuiteName. Swift 3.0 renamed this and I think userDefaultsObject.addSuite(named: …) was the closest thing I saw, I missed the renamed constructor.Intussusception
I have followed all the steps given in question and above answer..still I am receiving nil while getting value..Placid
P
0

if you suffer this problem when you try to save data to extension APP by using userDefault,maybe you had written this code : [[NSUserDefaults standardUserDefaults] initWithSuiteName:@"group.xxx.com"];,this code reset default userDefault. Actually,the correct code is : [[NSUserDefaults alloc] initWithSuiteName:@"group.xxx.com"]; enter link description here

Postdate answered 20/10, 2016 at 10:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.