Is there any option to display in iOS Settings.bundle not only standard NSUserDefaults but also for a specific key. I would like to have the serverURL setting displayed inside iOS Settings app.
static NSString * const kConfigurationKey = #"com.apple.configuration.managed";
static NSString * const kConfigurationServerURLKey = #"serverURL";
NSDictionary *serverConfig = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kConfigurationKey];
NSString *serverURLString = serverConfig[kConfigurationServerURLKey];
I would like to avoid copying it from this dictionary to the main one just to have it displayed.
Related
I have added a settings bundle to my application consisting of a number of toggle switches, It is being used to display different images depending on which toggle is active. This works fine the first time but once the values has been set to YES it always returns YES.
I have deleted the data within NSUserDefaults using the below
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
which works if the settings are changed before every launch of the application. (not ideal). Has anyone come across this and know how the values can be updated and persist? Below is my code where i am retrieving and seeing from BOOL value
BOOL setImageOne = (BOOL)[[NSUserDefaults standardUserDefaults]valueForKey:#"ladbrokes"];
BOOL setImageTwo = (BOOL)[[NSUserDefaults standardUserDefaults]valueForKey:#"williamHill"];
if (setImageOne) {
self.clientLogoImageView.image = [UIImage imageNamed:#"clientOneLogo.png"];
}
if (setImageTwo) {
self.clientLogoImageView.image = [UIImage imageNamed:#"clientTwoLogo.png"];
}
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
The bool will be stored within an NSNumber object, as primitive types cannot be stored in Objective-C collection classes, so this statement:
BOOL setImageOne = (BOOL)[[NSUserDefaults standardUserDefaults]valueForKey:#"ladbrokes"];
is basically the same as:
NSNumber *boolObj = #(NO);
BOOL b = (BOOL)boolObj; // b == YES
when what you intended was:
BOOL b = [boolObj boolValue]; // b == NO
Use [NSUserDefaults boolForKey] instead.
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"];
}
So this is my first time trying to save data in an iOS app. I've pieced together this code from various answers on this site in order to save a high score for a game I'm making. I created a plist named saves.plist (in my Supporting Files folder) and added a row of key #"bestScore" and type Number. The test log returns that the save is successful, and everything works; however, when I go to look at the plist after, nothing seems to have changed (the value of bestScore is 0). Am I saving to a different plist that is automatically created in my code? If this is the case, what is the point of being able to create plists in Xcode, and what is the best practice to use here as far as where/how to create/store/access plists?
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.fm = [NSFileManager defaultManager];
self.destPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];//Documents directory
self.destPath = [self.destPath stringByAppendingPathComponent:#"saves.plist"];
// If the file doesn't exist in the Documents Folder, copy it.
if (![self.fm fileExistsAtPath:self.destPath]) {
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"saves" ofType:#"plist"];
[self.fm copyItemAtPath:sourcePath toPath:self.destPath error:nil];
}
}
- (void)saveBestScore{
NSNumber *bestScoreBox = [NSNumber numberWithUnsignedLong:self.bestScore];
NSDictionary *data = #{bestScoreBox: #"bestScore"};
BOOL successful = [data writeToFile:self.destPath atomically:YES];
successful ? NSLog(#"YES") : NSLog(#"NO");
}
When you say
when I go to look at the plist after, nothing seems to have changed
(the value of bestScore is 0)
Do you mean looking at the plist in xcode project files ? You have copied the plist into a device directory and therefore you wont be able to see the change in xcode.
If you are using simulator, you can access the changed plist at:
~/Library/Application Support/iPhone Simulator/<Simulator Version>/Applications/<application>/Documents/
One easy way of storing score is to use NSUserDefault, which is a dictionary like persistence store for each application.
Set Score:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#(score)
forKey:#"score"];
[userDefaults synchronize];
Get Score:
int score = [[[NSUserDefaults standardUserDefaults] objectForKey:#"score"] intValue];
UPDATE:
rmaddy mentioned NSUserDefaults supports setInteger:forKey and integerForKey: Therefore you dont need to wrap the score into a NSNumber
When you write an NSDictionary to a plist using writeToFile:, the keys and values in the dictionary must follow strict rules. All keys must be NSString objects and all values must be property values (NSString, NSNumber, NSDate, NSData, etc.).
The problem you have is your dictionary has a key that is an NSNumber, not an NSString.
It appears you actually create the dictionary incorrectly. The syntax is:
#{ key : value, key : value, ... }
Change your code to:
NSDictionary *data = #{ #"bestScore" : bestScoreBox }; // key : value
Side note - your last line should be:
NSLog(#"%#", successful ? #"YES" : #"NO");
It's not good practice to use the ternary operator to run two different commands. It's meant to return one of two values.
I am looking at transitioning an app of mine from standard iOS Objective C to C# using MonoTouch.
In my Objective C code I am generating a unique identifier and saving it to NSUserDefaults to validate and check on subsequent logins. Here is the method that I am using for that:
- (NSString *) localUuid {
NSString * ident = [[NSUserDefaults standardUserDefaults] objectForKey:UUID];
if(!ident){
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
ident = [NSString stringWithString:(__bridge_transfer NSString *)uuidStringRef];
[[NSUserDefaults standardUserDefaults] setObject:ident forKey:UUID];
[[NSUserDefaults standardUserDefaults] synchronize];
}
return ident;
}
I am having problems getting something similar to work in C# with MonoTouch though.
I haven't found a version of the CFUUID__ methods available with Mono.
Also, while there appears to be a NSUserDefaults.StandardUserDefaults.SetValueForKey method, there isn't a straightforward GetValueForKey method.
Does anyone more experienced with Monotouch know a better way to do this?
CFUUID is not bound because it's easier to use .NET System.Guid to achieve the same. E.g.
var uuid = Guid.NewGuid ();
string s = uuid.ToString (); // if a string is preferred
Also, while there appears to be a NSUserDefaults.StandardUserDefaults.SetValueForKey method, there isn't a straightforward GetValueForKey method.
There are safely type methods to do the same, e.g.:
NSUserDefaults settings = NSUserDefaults.StandardUserDefaults;
settings.SetString (s, "key");
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.