I can't find any tutorial or guide to show me how to save preferences with my Custom iOS 8 keyboard.
I have different skins and the user can cycle to all the skins. However if the user dismisses the keyboard then loads it back up, it will load the initial skin.
I know other keyboards have found a way to load Skins and remember which one was selected.
I also have 2 different layouts for my keyboard
QWERTY and DVORAK
I would like to also save that preference so user can change their selection when in my app.
Keyboard is done in Swift/Obj-C (not sure if that matters)
1. Create an app group for your host app and your custom keyboard
Select your host app's target, go to Capabilities, scroll to App Groups and add one by clicking on "+" sign. Type the name of your group.
Do the same with your keyboard's target but now simply add a group by ticking the recently added app group.
2. Now you can use NSUserDefaults to store & share data with your host app
Store data:
_userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app-group-name"];
[_userDefaults setObject:#"theme-dark" forKey:#"KeyboardTheme"]; // save data
Restore data:
_userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app-group-name"];
_theme = [_userDefaults objectForKey:#"KeyboardTheme"];
if ([theme isEqualToString:#"theme-dark"])
{
...
}
- Use constants & NS_ENUM instead of comparing strings.
- Full access has to be activated.
Apple Resources: head for “Sharing Data with Your Containing App“
I know I need to use NSUserDefaults but not sure how to implement it.
Related
I have a login view controller in which the user enters their preferences like whether or not he wants to activate certain UI features.
I store these as variables whose getters and setters directly access UserDefaults, here is an example of one of these:
class Preferences {
static var likesSpaghetti : Bool {
set (likesSpaghetti) {
UserDefaults.standard.set(likesSpaghetti, forKey: "likesSpaghetti")
}
get {
return UserDefaults.standard.bool(forKey: "likesSpaghetti")
}
}
}
So that whenever I want to set any of these I simply write something like this:
Preferences.likesSpaghetti = false
Now, my question is: Can I set these variables every time the user flicks the on/off switch or should I keep the preference represented as a local variable and then only set:
Preferences.likesSpaghetti = spaghettiSwitch.isOn
when the user segue's away from the loginViewController? Is every access of UserDefault instant and quick? or is it laggy and should be used mercifully?
Edit after closing this question: So I learned to not prematurely optimize, and that it is probably ok within the scope of a few dozen elements. So I should be fine. I'm going to just update every time the user modifies anything so that my code is a lot easier to read and maintain.
Thanks everyone!
Your code is just fine. Don't worry about such optimizations until you actually encounter an issue. Trust that UserDefaults is implemented smartly (because it is). There is nothing "laggy" about setting something as simple as a Bool in UserDefaults.
You also wish to review another one of my answers which is related to this question: When and why should you use NSUserDefaults's synchronize() method?
Actually userDefaults (it's originally a plist file) is used for this purpose which is storing app settings and that light-wight content creating a variable may consum memory if you have to configure many of them , besides not reflecting the new setting change directly to defaults made by user , may cause un-expectable old settings to happen at the time of change such as a localized alert or part of code (such as push notification callback) that check the same setting where the user thinks it's already reflected
Adding to both #rmaddy #Sh_Khan, if you think about the security aspect of it, NSUserDafault is exactly for the details which is app specific such as settings, preferences or some configurations which are not security sensitive while things like passwords, usernames and sensitive data are not recommended to store in UserDefaults. You should use services like keychain which is encrypted for such data.
I'm having trouble understanding how I can have dynamic data fed into a MultiValue attribute inside the Root.plist file of a Settings-Watch.bundle.
When fetching some REST API I would like to retrieve some map (dictionary) and set that data as the list of choice in my Watch Settings Bundle so that the user can select a specific value from it inside the Apple Watch application on the iPhone/iPad.
I tried like this:
NSUserDefaults *watchPrefs = [[NSUserDefaults alloc] initWithSuiteName:#"group.foo"];
// foo and titles are NSArray* of NSString.
// I also tried by giving it a NSDictionary* whose keys are what's in foo and values reflecting bar
[watchPrefs registerDefaults:#{#"preferedAccount": #{#"Values": foo, #"Titles": bar}}];
[watchPrefs synchronize];
But even when I close the app these data are not shown in the Watch application > My application.
I configured the preferedAccount as a MultiValue inside the Root.plist file.
It must be dynamic in that case because the data reflects the logged user and so cannot be known in advance.
Is it even possible to display dynamic data there ?
Thanks
I have an in app purchase issue... I have an iPad app I'm upgrading. Previously used MKStoreKit. Started to upgrade to the latest version, but it turned out to be too complicated and too different to just "plug-in". Created a new "store kit" from scratch, which is much simpler and is built for iOS5+ and is ARC compliant.
Scenario: I have 3 spots to purchase. 1) is a full upgrade from a popover; 2) is an "icons" popover, which allows the user to purchase sets of icons for use in the app; 3) is a "backgrounds" popover, which allows the user to purchase sets of backgrounds for use in the app. All are in different views within the app.
Obviously, the available items all have to be available, but they also need to be segregated into the different popovers.
I have a "store manager" and a helper for the manager. The manager has a class method which includes all of the products listed in a set, and are accessed via a single "productIdentifier" variable in the manager. The actual items (images) are included in the app and are connected to an SQL database. I have played with additional sets, and have used subarrayWithRange. I have the correct number of sets showing in the popovers, although they are not showing the correct count, nor the correct images in each set.
I am looking for suggestions on how to separate these products into their unique "categories", while retaining the product identifier class of the manager, so that they feed back to the manager. I'm not looking for someone to solve it "for me"... I fully believe in solving one's own issues. I'm merely looking for a few suggestions in steering me in the correct path.
Should I create separate class methods for each type of purchase? Subsets within the main set?
Have any suggestions on how I could solve this issue? Any and all are appreciated.
I was able to solve this issue by using a refresh table method. I simply use different ranges for the 3 different spots.
-(void)reloadData
{
_products = nil;
[TJ_IAPHelper.sharedInstance requestProductsWithCompletionHandler:^(BOOL success, NSArray *products)
{
// by using subarrayWithRange, we limit what is displayed in the table
// those items that actually correspond to the background sets
// from the Apple store
_purchaseableBackgrounds = [products subarrayWithRange:NSMakeRange(0, 6)];
if (success)
{
_products = _purchaseableBackgrounds;
[self.tableView reloadData];
}
[self.refreshControl endRefreshing];
}];
}
I want to display a view which contains the disclaimer for my app, only once. like, after you read it and press agree , never to show up again. when the app starts next time , jump straight to the next view in the storyboard (the login or whatever view). :( please explain the solution as detailed as possible because I'm new to iOS programming. thank you very much !
PS: I'm talking about ViewController for iOS in Xcode :)
First time try to read from NSUserDefaults and check if a property is there, if not show the view controller and set a property in user defaults as,
In didFinishLaunching delegate method,
NSString *myString = [[NSUserDefaults standardUserDefaults] stringForKey:#"DidShowDisclaimer"]
if ([myString iEqualToString:#"YES"]) {
//show the view controller and once they have accepted save this key
[[NSUserDefaults standardUserDefaults] setValue:#"YES" forKey:#"DidShowDisclaimer"];
[[NSUserDefaults standardUserDefaults] synchronize]; //next time when the app is launched it will never execute this if condition
}
So next time onwards, it would have been yes, and you never have to show again
You will need to store an NSUserDefault boolean to your app to know if your user accepted the user agreement or not.
So in terms of steps
1. app opens
2. check if boolean has been previously set
3. If not show them the agreement
4. If they agree then set the boolean to signify they've accepted and your check will always fail when the app is opened so you can skip the step.
I have an application that is based on a UINavigationController; I wish to add a "Setting" page where the user will have the ability to set some features like Language and some other preferences.
Currently the UIViewController where I wish to have the Setting fields in is 2 levels under the RootViewController (i.e. there is a "main view" >> you click on a button and enter another UIViewController and form there you should be able to enter the Setting UIViewController).
I'm not clear about how I'm supposed to save this data and how to call it upon application load.
I read some blogs about NSUserDefaults and about Singleton but I'm not clear how should I use them.
Where should I create the data attributs that will later on maintain the user preferences? Should I create them on the AppDelegate or on the MySettingsViewController (the UIViewController that I'm creating)?
Should I use a Singleton attribute, and if so, where should it be created?
When you say "Singleton", do you actually mean creating a Static attribute?
Is there another way to communicate between 2 controllers that are not directly connected one to the other (I can transfer data from the "bottom" ViewController to the RootViewController passing it via the UIViewController in the middle, but it seems weird and ineffective)?
Any direction / tutorial will be appreciated!
Definitely use NSUserDefaults. It's great, and Apple recommends it.
To set a setting:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"Setting 1"];
You can also store other things, such as text, numbers, etc. Much more than a simple boolean.
To check the setting:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"Setting 1"]) {
//ok, do the thing here
}
I'd use http://inappsettingskit.com/ rather than roll my own. I've used it in almost every application I work on and it handles app settings perfectly for just this sort of scenario.