I'm using in-app settings from http://www.inappsettingskit.com/. It is really great but I can't figure out how to have the settings automatically load into the in-app settings on launch.
When I launch my app for the first time, all of the in-app multi-value cells are blank.
What I want to know is how to load them when the app is launched the first time?
The defaults are loaded in from the settings bundle, but aren't being passed through to the in-app settings...currently this is my code that does that...
-applicationDidFinishLaunching:
//It is here that we set the defaults
NSString *textValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"title_key"];
//If the first value is nil, then we know that the defaults are not set.
if(textValue == nil)
{
//We set the default values from the settings bundle.
//Get the bundle path
NSString *bPath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPath = [bPath stringByAppendingPathComponent:#"Settings.bundle"];
NSString *plistFile = [settingsPath stringByAppendingPathComponent:#"Root.plist"];
NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile];
NSArray *preferencesArray = [settingsDictionary objectForKey:#"PreferenceSpecifiers"];
NSDictionary *item;
NSString *title_Key;
NSString *detail_Key;
NSString *sort_Key;
for(item in preferencesArray)
{
//Get the key of the item.
NSString *keyValue = [item objectForKey:#"Key"];
//Get the default value specified in the plist file.
id defaultValue = [item objectForKey:#"DefaultValue"];
if([keyValue isEqualToString:#"title_key"]) title_Key = defaultValue;
if([keyValue isEqualToString:#"detail_key"]) detail_Key = defaultValue;
if([keyValue isEqualToString:#"sort_key"]) sort_Key = defaultValue;
}
//Now that we have all the default values.
//We will create it here.
NSDictionary *appPrerfs = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2], #"title_key",
[NSNumber numberWithInt:4], #"detail_key",
[NSNumber numberWithInt:2], #"sort_key",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appPrerfs];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I have also tried the suggestion in the first answer, creating a seperate userDefaults.plist and have the defaults being loaded from there, my app is still getting the defaults but they are not passing through to in-app settings.
I thought that it should look like this on the first launching the app...
You want to register your NSUserDefaults first. Check out this description.
Related
I was using xCode 3.2 and then moved to xCode 4.2 and getting some values from Settings.bundle ... it was working fine.
Mean while I need to edit some values in Settings.bundle but The Root.plist file was not showing so I follow the below procedure but did not make any change in file.
1) Click on the Settings.Bundle file, go over to the utilities window,
and look in the File Inspector.
2) Using the drop-down, change the file type to 'Application Bundle'
After that I could see Root.plist but now could not get its values in application. Actually getting Null instead of value.
Below is code and image of Settings.bundle
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
host = [defaults stringForKey:#"meter_preference"];
if(host == nil)
{
host = #"10.20.20.1";
DDLogError(#"Meter host is nil from NSUserDefaults, defaulting to %#", host);
}
I got the solution, just call the below code in applicationDidFinishLaunchingWithOptions to initialize User defaults. and it works
Replace somePropertyYouExpect in first line with property you stored in User Defaults.
if (![[NSUserDefaults standardUserDefaults] objectForKey:#"somePropertyYouExpect"]) {
NSString *mainBundlePath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPropertyListPath = [mainBundlePath
stringByAppendingPathComponent:#"Settings.bundle/Root.plist"];
NSDictionary *settingsPropertyList = [NSDictionary
dictionaryWithContentsOfFile:settingsPropertyListPath];
NSMutableArray *preferenceArray = [settingsPropertyList objectForKey:#"PreferenceSpecifiers"];
NSMutableDictionary *registerableDictionary = [NSMutableDictionary dictionary];
for (int i = 0; i < [preferenceArray count]; i++) {
NSString *key = [[preferenceArray objectAtIndex:i] objectForKey:#"Key"];
if (key) {
id value = [[preferenceArray objectAtIndex:i] objectForKey:#"DefaultValue"];
[registerableDictionary setObject:value forKey:key];
}
}
[[NSUserDefaults standardUserDefaults] registerDefaults:registerableDictionary];
[[NSUserDefaults standardUserDefaults] synchronize];
}
From your code , try this thinks..
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
host = [defaults stringForKey:#"meter_preference"];
if(!host == nil)
{
host = #"10.20.20.1";
DDLogError(#"Meter host is nil from NSUserDefaults, defaulting to %#", host);
}
OR
Review this link may be helped you...
iPhone - reading Setting.bundle returns wrong values
NSUserDefaults Settings Bundle Plist
I am encountering a strange issue in iOS 8.2 where [NSUserDefaults standardUserDefaults] is returning nil on iPhone. This same logic untouched has worked on all previous releases of iOS. I have a universal app which has two different settings.plist one for iPad and the other for iPhone list as follows;
Settings.bundle-
-Root.plist
-Root~iphone.plist
When installed on devices the correct settings pane displays and the user can input the appropriate values for the given fields. Though in my app at runtime [NSUserDefaults standardUserDefalts] returns a nil object.
What might I be doing wrong? Has Apple changed what is expected in 8.2?
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
userDefaults is always nil no matter what preferences are set in system settings.
Did you set the dictionary to use as "Settings.bundle/Root.plist"?
// Register the preference defaults from file "Settings.bundle/Root.plist"
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"Settings.bundle/Root"
ofType:#"plist"]];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
Thereafter [NSUserDefaults standardUserDefaults] no longer is nil.
In my case, the dictionary used by [NSUserDefaults standardUserDefaults] looks like this in the debugger:
{
PreferenceSpecifiers = (
{
DefaultValue = 1;
Key = sortByDistance;
Title = "Sortiere nach Entfernung";
Type = PSToggleSwitchSpecifier;
}
);
StringsTable = Root;
}
To access the preferences I've written a tiny method:
- (id) preferenceValueForKey: (NSString *)key {
NSArray *preferences = [[NSUserDefaults standardUserDefaults] arrayForKey:#"PreferenceSpecifiers"];
NSUInteger index = [preferences indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [[obj valueForKey:#"Key"] isEqualToString:key];
}];
return [preferences[index] valueForKey:#"DefaultValue"];
}
I have an app settings file which displays the version number for our app. The idea is to update the Root.plist on compile so that we don't have to update two places rather than one. We update theBuild settings version and would like those settings to update the Root.plist on compile.
This code extracts the information for the build settings, how do I update the Root.plist file?
NSString *appBuildNo = [[NSBundle mainBundle]objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *appBuildVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSString *appBuildStr = [NSString stringWithFormat:#"%# Build %#", appBuildNo, appBuildVersion];
NSURL * settingsURL = [[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:#"Settings" withExtension:#"bundle"]]
URLForResource:#"Root" withExtension:#"plist"];
NSDictionary * settingsDict = [NSDictionary dictionaryWithContentsOfURL:settingsURL];
NSArray * settingsArr = [settingsDict objectForKey:#"PreferenceSpecifiers"];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
for( NSDictionary * setting in settingsArr ){
NSString * key = [setting objectForKey:#"DefaultValue"];
[defaults setValue:appBuildStr forKey:key];
[defaults synchronize];
break;
}
The idea is that defaults updates Root.plist but it is not working. Any help would be appreciated
Droppy was very helpful in helping me to fix this. After setting up my Settings Bundle and the Root.plist file, I added the following code to my AppDelegate and called it from the didFinishLaunchingWithOptions.
- (void)updateVersionInfo
{
//This method updates the Root settings to display current Version and Build No in Settings Bundle
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *appVersionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSString *appBuildNo = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *versionNumberInSettings = [NSString stringWithFormat:#"%# Build %#", appBuildNo, appVersionNumber];
[defaults setObject:versionNumberInSettings forKey:#"version"];
}
This code then adds the contents of the Version in the info.plist file to my Settings Bundle.
I am using NSUserDefaults to store some integer settings for my app, but I want to register default values for these settings, using code like this:
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:(NSInteger)0, #"PMChordColour", (NSInteger)1, #"PMTextColour", (NSInteger)0, #"PMBackgroundColour", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
The values are read in my app using
NSInteger setColour = [[NSUserDefaults standardUserDefaults] integerForKey:#"PMChordColour"];
The problem with this is that NSDictionary does not allow scalar values to be stored.
Is there any way of registering defaults that allows integers to be stored? I realise that I could use NSNumber but it seems like unnecessary overhead.
No, you have to use NSNumber. It's necessary overhead.
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:13], #"id", nil];
int integer = [[dict objectForKey:#"id"] intValue];
I have an iOS application with a settings.bundle that handles various settings for my application with Switch toggle. I set default values in my root.plist file (using the DefaultValue property) to YES but any time the application launches on a device or the iOS simulator all values go NO. It worked well only on the first launch.
I am retrieving the defaults with this code (am I doing something wrong here?):
NSUserDefaults *localeDefaults = [NSUserDefaults standardUserDefaults];
BOOL ENWORDS = [localeDefaults boolForKey:#"localetime"];
The Default Value is used by Settings.app for display purposes only. If you don't change the value in the settings app nothing is saved to NSUserDefaults.
You have to register the default values yourself. Use something like this in application:didFinishLaunchingWithOptions::
NSDictionary *userDefaultsDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], #"localetime",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsDefaults];
This blog post might help : http://greghaygood.com/2009/03/09/updating-nsuserdefaults-from-settingsbundle
tl;dr - until the user opens the settings page then the defaults aren't copied into your app. This is the expected behavior by Apple.
Personally, I think this is terrible. It means that you will have to set your defaults in code just in case the user starts your app without going to the settings page first (which will be true for about 99% of use cases!)
The problem is the type of default Value must be boolean not string ;) delete this value and add a another default Value property again
hope this helps
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//< Register Defaults
NSString *settingsBundlePath = [[NSBundle mainBundle] pathForResource:#"Settings" ofType:#"bundle"];
NSBundle *settingsBundle = [NSBundle bundleWithPath:settingsBundlePath];
NSString *rootPlistPath = [settingsBundle pathForResource:#"Root" ofType:#"plist"];
NSDictionary *settingsDict = [[NSDictionary alloc] initWithContentsOfFile:rootPlistPath];
NSArray *settingsItems = [settingsDict objectForKey:#"PreferenceSpecifiers"];
NSMutableDictionary *defaultDict = [NSMutableDictionary new];
for (NSDictionary *itemDict in settingsItems) {
if ([itemDict objectForKey:#"DefaultValue"]) {
[defaultDict setObject:[itemDict objectForKey:#"DefaultValue"] forKey:[itemDict objectForKey:#"Key"]];
}
}
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultDict];
//< Following Code
}
You can check whether the value has been set by getting objectForKey and checking whether it is nil.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
id dataExists = [userDefaults objectForKey:#"light_switch"];
BOOL lightSwitch;
if (dataExists != nil) {
lightSwitch = [userDefaults boolForKey:#"light_switch"];
NSLog(#"light_switch is %d", validateCertificates);
} else {
lightSwitch = YES; // default value
NSLog(#"light_switch not set, default value is %d", validateCertificates);
}