Storing bool in shared NSUserDefaults always returns false

637 views Asked by At

I've set up App Groups for my app so that I can access the same NSUserDefaults in the app and in my keyboard extension. I have a problem though. I can successfully write a boolean to the defaults but when I access it in the keyboard, it always returns false. I know for a fact the id it's using for the key and the suite name are the exact same. I verified App Groups is indeed enabled for both the app and the keyboard and the suite name matches the app group identifier exactly. What could cause it to always be false when accessing from within the keyboard?

In the app:

NSUserDefaults *SharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.myname.sharedPrefsName"];
[SharedDefaults setBool:YES forKey:@"com.myname.appname.dataName"];
[SharedDefaults synchronize];

I did confirm it did successfully get set to YES the next time I launch the app:

NSUserDefaults *SharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.myname.sharedPrefsName"];
BOOL dataIsYes = [SharedDefaults boolForKey:@"com.myname.appname.dataName"]; //YES

Yet in the keyboard it is always false:

let sharedprefs = NSUserDefaults(suiteName: "group.com.myname.sharedPrefsName")!
let data = sharedprefs.boolForKey("com.myname.appname.dataName") //false
2

There are 2 answers

0
Jordan H On BEST ANSWER

I found the answer in the App Extension Programming guide.

By default, a keyboard has no network access and cannot share a container with its containing app. To enable these things, set the value of the RequestsOpenAccess Boolean key in the Info.plist file to YES.

To fix the issue I had to change the RequestsOpenAccess field to YES in the keyboard's Info.plist > NSExtension > NSExtensionAttributes > RequestOpenAccess. Then remove the keyboard in Settings, delete the app, run it again, and add the keyboard again. Then be sure to tap on the keyboard name and then flip the switch to Allow Full Access.

If users don't enable Full Access, the extension will still be able to access the shared container (iOS 8.3+ only) but it will not be able to write to it, for security and privacy reasons. In 8.2- you cannot read from it without open access granted.

1
Duncan C On

Don't use alloc/init for NSUserDefaults. It's a singleton. You're supposed to use the class method standardUserDefaults to get a pointer to the shared user defaults object:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];