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.
Related
I know that there are other same questions as mine. But I think that I have tried everything and I still can't be able to find the NSUserDefaults plist file in my simulator folder. I made sure that I got the right ID for the simulator and I wasn't able to find the NSUserDefaults plist as I want to check exactly what values are being saved. Does anyone know what is the exact name of the file that I should be searching for?
For info, I am searching in the following path:
/Users/username/Library/Developer/CoreSimulator/Devices/<device_id>/data/Library/Preferences
Does anyone know if I am doing it wrong? How can I find that file?
Thank you for your help!
you can print the location by asking at runtime.
Each time you compile and run simulator the folders may differ from before.
how to write NSUserDefaults
NSUserDefaults *userdef = [NSUserDefaults standardUserDefaults];
[userdef setObject:#"testString" forKey:#"testkey"];
[userdef synchronize]; //dont forget synchoniszing after setting new objects
how to read NSUserDefaults
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
NSString *result = [defs objectForKey:#"testkey"];
NSLog(#"read out userdefs = %#",result);
If you did not set any NSUserDefaults yet, there is no file.
Otherwise where is your <BundleIdentifier>.<appName>.plist ?
NSArray *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryFolder = [path objectAtIndex:0];
NSString *appID = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleIdentifier"];
NSString *userdefFile = [NSString stringWithFormat:#"%#/Preferences/%#.plist", libraryFolder, appID];
NSLog(#"NSUserDefaults File located at: %#", userdefFile);
I'm trying to read and write data to my plist file, While the reading part goes well, the writing part does nothing.
I might be mistaken for the writing part - i can't see any changes in my file under my bundle - it is still empty after my changes, and when i close the app and open it again - i still see empty email address line.
The code for writing (and placing the plist in the document folder for future writings)
NSFileManager *fileManger=[NSFileManager defaultManager];
NSError *error;
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
NSString *destinationPath= [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSLog(#"plist path %#",destinationPath);
if ([fileManger fileExistsAtPath:destinationPath]){
NSLog(#"database localtion %#",destinationPath);
//return;
}
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:#"userData.plist"];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: sourcePath];
NSString *emailAddress = (NSString *)[dict objectForKey: #"emailAddress"];
if([emailAddress isEqualToString:#""])
{
// Do stuff
}
And for writing
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath =[pathsArray objectAtIndex:0];
NSString *destinationPath = [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile: destinationPath];
[plistDict setValue:#"myEmail#gmail.com" forKey:#"emailAddress"];
[plistDict writeToFile:destinationPath atomically: YES];
But as i said, nothing is changed in the file itself, and not even when i save, close the app and open it again (the string is always empty on my reading part)
Any help will be more than welcomed.
This question already has answers here:
File write with [NSBundle mainBundle] fails
(5 answers)
Closed 8 years ago.
I'm reading and writing variables to a text file in my app.
It works perfectly fine when testing it in the simulator, but somehow when testing it on the iPhone it can only read the file but not write/save anything
Here's my method for saving my variables ("\n" is used for line breaking):
NSString path = [[NSBundle mainBundle] pathForResource:#"settings" ofType:#"txt"];
- (void)saveSettings {
[[NSString stringWithFormat:#"%d\n%d", firstInt, secInt] writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
As I said: works in the simulator but doesn't work on any iDevice.
Does anyone got a idea why it's not working? Changing "atomically" to "NO" does nothing
You can't write to the bundle. Among other reasons because the bundle is part of the signature in the app and that can't be changed. You can write to other directories, en particular the Documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *write_file = [NSString stringWithFormat:#"%#/settings.txt",
documentsDirectory];
You will be able to write to write_file.
Short answer: You can't write into the main bundle.
Long answer: You should really use the preferences for this:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:[NSString stringWithFormat:#"%d\n%d", firstInt, secInt]
forKey:#"yourPref"];
BOOL saved = [prefs synchronize];
or even better, like that:
NSInteger firstInt = 0;
NSInteger secInt = 0;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:firstInt forKey:#"firstInt"];
[prefs setInteger:secInt forKey:#"secInt"];
BOOL saved = [prefs synchronize];
So when I click "View User Record" button I want to display whatever value of Score and Live of a view controller and store it in a plist as an array. And then those values from the plist will be displayed into the table view
try this for adding value in plist file .
NSString* plistPath = nil;
NSFileManager* manager = [NSFileManager defaultManager];
if (plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"Contents/Info.plist"])
{
if ([manager isWritableFileAtPath:plistPath])
{
NSMutableDictionary* infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
[infoDict setObject:[NSNumber numberWithBool:hidden] forKey:#"LSUIElement"];
[infoDict writeToFile:plistPath atomically:NO];
[manager changeFileAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] atPath: [[NSBundle mainBundle] bundlePath]];
}
}
And This is for Get Value from plist file.
NSBundle* mainBundle = [NSBundle mainBundle];
// Reads the value of the custom key I added to the Info.plist
NSString *value = [mainBundle objectForInfoDictionaryKey:#"key"];
//Log the value
NSLog(#"Value = %#", value);
// Get the value for the "Bundle version" from the Info.plist
[mainBundle objectForInfoDictionaryKey:#"CFBundleVersion"];
// Get the bundle identifier
[mainBundle bundleIdentifier];
i hope this code is useful for you.
I'm trying to use NSLocalizedStringFromTable but with no results. I've got created Profile.strings file, clicked localized, in project settings I add Polish and English languages, so my file has 2 "files" inside and I typed the same strings with other values but when I switch languages and restart app there is still one localization used (Polish).
Profile.strings in Xcode:
Profile.strings
Profile.strings (Polish)
Profile.strings (English)
Polish:
"fullName.placeholder" = "Imie i nazwisko";
"emailAddress.placeholder" = "Adres email";
"phoneNumber.placeholder" = "Numer telefonu";
English:
"fullName.placeholder" = "Full name";
"emailAddress.placeholder" = "Email address";
"phoneNumber.placeholder" = "Phone number";
To get value I call:
NSLocalizedStringFromTable(#"fullName.placeholder", #"Profile", #"");
Any time I call this I've got value from Profile.strings (Polish)
What I'm doing wrong?
try to Reset Content and Settings of simulator it will work (:
Maybe you're not changing the language correctly. Try doing it in code. Like this:
- (void) setLanguage:(NSString*) l{
for (NSString *language1 in [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"]) {
NSBundle *bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language1 ofType:#"lproj"]];
NSLog(#"%#: %#", language1, NSLocalizedStringFromTableInBundle(#"left", #"Localizable", bundle1, nil));
}
NSBundle *bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:l ofType:#"lproj"]];
/*
if ([l isEqualToString:#"en"]) {
bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"English" ofType:#"lproj"]];
}
*/
if (bundle1 == nil)
//in case the language does not exists
[self resetLocalization];
else
bundle = bundle1;
NSMutableArray *langs = [NSMutableArray arrayWithArray: [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"]];
[langs removeObject:l];
NSMutableArray *newLangs = [NSMutableArray arrayWithObject:l];
[newLangs addObjectsFromArray:langs];
[[NSUserDefaults standardUserDefaults] setObject: newLangs forKey:#"AppleLanguages"];
}
And then you can do
[self setLanguage:#"en"];