Xcode 10.2 widget can't access UserDefaults in release build

Since I've updated from Xcode 10.1 to 10.2, I've got a lot of issues where release builds were behaving different as debug builds. In most of those cases, some functions weren't invoked at all on the release build where they would be on debug builds.


Now I've got this following issue, which I can reproduce with a simple new project (to be sure the issue isn't caused by any added framework or something):


I can't retrieve data from a UserDefaults group from a Today Extension on release build.



I created a new project and registered an app group `group.mydomain.test`.

In the AppDelegate I added:


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        let shared = UserDefaults(suiteName: "group.mydomain.test")
        shared?.set("MyTestValue", forKey: "MyTestKey")
        print("Shared value for 'MyTestKey': \(shared?.string(forKey: "MyTestKey") ?? "nil")")

        return true
    }


Which correctly prints the value being set.


Then I added a Today Extension, replaced the 'Hello world' label with a new label which I linked to the view controller.

In TodayViewController I added:


func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
        let shared = UserDefaults(suiteName: "group.mydomain.test")
        self.testLabel.text = (shared?.string(forKey: "MyTestKey")) ?? "nil"

        completionHandler(NCUpdateResult.newData)
    }


When I run the app as a `debug` build, everything works fine and the extension will show a label with "MyTestValue".

When I run the app as a `release` build, the extension will show "nil".


I went to the apps container folder in the simulator and I do see the group's plist in preferences and it does contain the set value.

Even when I change all build settings of the release to match the debug settings (e.g. optimization), it still doesn't work.

Replies

Could you test wht is the content of shared in widgetPerformUpdate, in both cases (debug / release)

In situations like this it’s important to tease apart Debug/Release build vs Development/Distribution signing. My advice:

  • Test on a device, not the simulator. The simulator is a fine tool, but in this case you really want to make sure you’re testing as your users will be using the product.

  • Archive your app (Product > Archive). This will create a Release build. Then use Xcode’s Organizer to export it twice, first using Development signing and second using ad hoc Distribution signing. This will tell you whether the problem lies with the Release build (both versions fail) or Distribution signing (only the ad hoc version fails).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"