5

I need to save data to NSUserDefault in my iOS Custom Keyboard. I have successfully created App Groups and entitlement in developer portal and XCode.

Here is how i save my value with UISwitch

- (IBAction)switchAction:(id)sender
{
    [self.defaults setBool:self.myKey.on forKey:@"myValue"];

    [self.defaults synchronize];
}

and here is how i load value in KeyboardView.

self.defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.mycompany.customkeyboard"];

if([self.defaults boolForKey:@"myValue"])
{
    self.backgroundColor = [UIColor redColor];
}

else
{
    self.backgroundColor = [UIColor blackColor];
}

It's doesn't work and doesn't load value.

How can i save and load data?

Fire Fist
  • 7,032
  • 12
  • 63
  • 109
  • possible duplicate of [Communicating and persisting data between apps with App Groups](http://stackoverflow.com/questions/24015506/communicating-and-persisting-data-between-apps-with-app-groups) – Andrew Jun 16 '14 at 14:00
  • No. i have already found that questions. my questions is i don't know how to load data from NSUserDefault. – Fire Fist Jun 16 '14 at 14:01
  • I was referring to [my answer to that question](http://stackoverflow.com/a/24063144/2446155), which I have slightly modified and replicated below. – Andrew Jun 16 '14 at 14:05

3 Answers3

4

Initialize your NSUserDefaults object like this in all applications in the app group and they will share the database:

[[NSUserDefaults alloc] initWithSuiteName:@"group identifier"];

Keep in mind everything from the [NSUserDefaults standardUserDefaults] database for each application will not carry over into this database.

The documentation indicates that [NSUserDefaults standardUserDefaults] should return the shared database like the above code does, however it does not. I filed this as a bug (rdar://17164758).

And don't forget to synchronize the database:

[yourDefaults synchronize];
Andrew
  • 15,357
  • 6
  • 66
  • 101
  • Yes , i do like you said and it doesn't load correctly. Here my codes. self.defaults = [[NSUserDefaults alloc] initWithSuiteName:@""]; if([self.defaults boolForKey:@"myValue"]) { self.backgroundColor = [UIColor redColor]; } else { self.backgroundColor = [UIColor blackColor]; } – Fire Fist Jun 16 '14 at 14:09
  • @Sabo The database starts out empty, so you will have to call your `switchAction:` method before any values will be set. Also ensure your app groups are setup correctly in your entitlements file, in your developer portal App ID, in your provisioning profile, and in Xcode. – Andrew Jun 16 '14 at 14:15
  • my SwitchAction is connection event with UISwitch, When UISwitch is on , i save value to NSUserDefault. However i can't load that data in KeyboardView. :( – Fire Fist Jun 16 '14 at 14:22
  • @Sabo Also ensure your app groups are setup correctly in your entitlements file, in your developer portal App ID, in your provisioning profile, and in Xcode. Make sure you are using `initWithSuiteName:@""` in both the extension and in the app itself. – Andrew Jun 16 '14 at 14:23
  • Yes , i have correctly setup my entitlements file because , i can see three setup that show in Capabilities and my entitlements file. – Fire Fist Jun 16 '14 at 14:25
  • @Sabo You can't trust Xcode. Make sure you are using initWithSuiteName:@"" in both the extension and in the app itself. – Andrew Jun 16 '14 at 14:26
  • Yes. i used your code like @"" in everywhere. – Fire Fist Jun 16 '14 at 14:26
  • @Sabo Check out your device console logs. Potentially post an excerpt of that if it sounds important. Any entitlements issues are logged in the console when your application is installed on a device. You should also attempt to test this in the simulator. Another user [had a similar issue](http://stackoverflow.com/q/24067975/244615). You might also consider reposting the code in your question now that you have modified it. – Andrew Jun 16 '14 at 14:33
  • @Sabo Remove `<` and `>` from your group identifier string. I meant that just as a placeholder. Those characters are probably messing it up :) – Andrew Jun 16 '14 at 14:52
  • @Manthan post a new question. – Andrew Sep 16 '14 at 10:33
  • @SantaClaus:http://stackoverflow.com/questions/25867535/app-crashes-on-setting-nsuserdefaults-setobject-method-in-ios8 – Manthan Sep 16 '14 at 11:27
  • 1
    To add to your answer. You also have to set RequestsOpenAccess = YES in app extension's Info.plist. It should go under NSExtension->NSExtensionAttributes (you have to create it with type dictionary) -> RequestsOpenAccess (Boolean) == YES. Only after this my app extensions could access app group's NSUserDefaults. – gladimdim Nov 02 '14 at 18:40
2

Ok, So I had a look around becuase I had the exact problem. What I did that worked was to add the main app and the extension to a group, Go to main project->Target->Capabilities and create a group (if you don't have one, or make one anyway) like this:

enter image description here

Then, go to the Extension below the target (E), again to Capabilities and add the extension to the group (exactly the same app group as you did for the main target), like this:

enter image description here

Then, once you have done both, in your main app, whenever you want to add something, create a new instance of NSUserDefaults, but for the Suitename equal to the groupname you made earlier. Like this:

NSArray *testing = @[@"first",@"Second",@"Third"];
NSUserDefaults *userd = [[NSUserDefaults alloc]initWithSuiteName:@"The gouprname I made earlier"];//This is exactly the same as the groupname
[userd setObject:testing forKey:@"ExtensionArray"];//set the object you want to share
[userd synchronize]; //It's a good idea to sync, just to be on the safe side.

In your extension's ViewController, use the same group name but to read the user defaults:

NSUserDefaults *sharedD=[[NSUserDefaults alloc]initWithSuiteName:@"Exactly the same groupname that I gave both in the Capabilities and when initialising the userdefault"];
self.testing = [[NSArray alloc]initWithArray:[sharedD arrayForKey:@"ExtensionArray"]];

And Voila! the array is there! I read somewhere that you can even add notification functionality for when the object changes, using a Wormhole class, but I can't find the link to it. I'm sure if you google for Wormhole class, you'll come across it.

I hope I could help, and if you found any more info, please share it with me.

Septronic
  • 1,156
  • 13
  • 32
0

You could load the right data from the containing app, so maybe set a new value in extension app will help.

[self.defaults setObject:newValue forKey:@"thisKeyIsJustUsedForSyn"]

And then load the right data.