I just want to output the version number of my ios application in a settings file.
I understand that I have to add the settings file to the application folder.
W
You can sync the Settings bundle to NSUserDefaults
, but weirdly it does not do at first. You have to first retrieve the values from Settings to NSUserDefaults
and then after that, edit that you make to those values in NSUserDefaults
are automatically applied to Settings bundle.
I referenced this nice article.
EDIT:
For your case to just to save your version, something like this would work. (This sample code is overkill in a way, but should be simpler to understand the flow)
//Get the bundle file
NSString *bPath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPath = [bPath stringByAppendingPathComponent:@"Settings.bundle"];
NSString *plistFile = [settingsPath stringByAppendingPathComponent:@"Root.plist"];
//Get the Preferences Array from the dictionary
NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile];
NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];
//Save default value of "version_number" in preference to NSUserDefaults
for(NSDictionary * item in preferencesArray) {
if([[item objectForKey:@"key"] isEqualToString:@"version_number"]) {
NSString * defaultValue = [item objectForKey:@"DefaultValue"];
[[NSUserDefaults standardUserDefaults] setObject:defaultValue forKey:@"version_number"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
//Save your real version number to NSUserDefaults
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
[[NSUserDefaults standardUserDefaults] setValue:version forKey:@"version_number"];
[[NSUserDefaults standardUserDefaults] synchronize];
This worked for me :
Edit the Root.plist as source : Right click on the file and choose Open As->Source Code
Add the part for the title :
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>DefaultValue</key>
<string>NoVersion</string>
<key>Key</key>
<string>Version</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
And in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Add this:
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
[[NSUserDefaults standardUserDefaults] setObject:version forKey:@"Version"];
It will work after the app has been launched the first time.
I had the same issue. To display Title property in the Settings.bundle
you need also to add "Default Value" (it could be empty).
1) Right click on the Title object (in my case it is Item 0) and select Add Row.
2) In the drop down of the created row select "Default Value"
3) In didFinishLaunchingWithOptions
set value to NSUserDefaults
you want to display, for example:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:@"0.0.1" forKey:@"appVersion"];
[defaults synchronize];
Result:
Ok, I had this problem too. The solution (sort of) was to provide a default value field and give that a value. This is actually explicitly stated in the documentation -- Default Value is a required field for the Title property, so if you don't specify it the title won't show in the settings pane. Unfortunately, I can't seem to CHANGE the value once it's set, possibly also as designed -- the documentation also states that it's a read only property. The solution I'm going to try is to just explicitly put the version number in my Root.plist file each time I make a new build. SUPER not ideal, but will work, I think.
EDIT: Check out this post on updating version number in settings bundle
EDIT: Ok, I got this working (thanks to that post, above, and a little hacking around with bash scripts, which I had very little experience with.) Here's the script (which I just wrote inline in a 'Run Script' build phase):
#!/bin/bash
builtInfoPlistPath=${TARGET_BUILD_DIR}/${INFOPLIST_PATH}
#increment the build number
buildNumber=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$builtInfoPlistPath")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$builtInfoPlistPath"
#compose the version number string
versionString=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$builtInfoPlistPath")
versionString+=" ("
versionString+=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$builtInfoPlistPath")
versionString+=")"
#write the version number string to the settings bundle
#IMPORTANT: this assumes the version number is the first property in the settings bundle!
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:0:DefaultValue $versionString" "Settings.bundle/Root.plist"
... and that's it! Works like a charm! Hope that helps with your problem, because it solved mine. Only problem now is a slight discrepancy with the build number ...
EDIT: ... which I fixed with vakio's second comment on this post, which instead sets the path to the info.plist to the one which is already processed (before the Run Script phase!)
EDIT: Here's my more up-to-date version, which is in an external file and verifies that some source files have changed before incrementing the build number:
#!/bin/bash
#note: for simplicity, it's assumed that there's already a bundle version (which is an integer) and a version string. set them in the Summary pane!
#get path to the BUILT .plist, NOT the packaged one! this fixes the off-by-one bug
builtInfoPlistPath=${TARGET_BUILD_DIR}/${INFOPLIST_PATH}
echo "using plist at $builtInfoPlistPath"
modifiedFilesExist=false
#this is the modification date to compare to -- there's a possible bug here, if you edit the built plist directly, for some reason. probably you shouldn't do that anyways.
compModDate=$(stat -f "%m" "$builtInfoPlistPath")
for filename in *
do
modDate=$(stat -f "%m" "$filename")
if [ "$modDate" -gt "$compModDate" ]
then
modifiedFilesExist=true;
echo "found newly modified file: $filename"
break
fi
done
if $modifiedFilesExist
then
echo "A file is new, bumping version"
#increment the build number
buildNumber=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$builtInfoPlistPath")
echo "retrieved current build number: $buildNumber"
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$builtInfoPlistPath"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
#compose the version number string
versionString=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$builtInfoPlistPath")
versionString+=" ("
versionString+=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$builtInfoPlistPath")
versionString+=")"
#write the version number string to the settings bundle
#IMPORTANT: this assumes the version number is the second property in the settings bundle!
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:1:DefaultValue $versionString" "Settings.bundle/Root.plist"
else
echo "Version not incremented -- no newly modified files"
fi
NSUserDefaults doen't write any values to a settings file. It will only save data in the user defaults plist in your app.
To save something in another file you will have to write this your own. Maybe this will help:
iOS - How to write a data in plist?
Another solution, without writing swift code is :
1/ Create a Setting bundle
This will create a new section for your app in the Settings of your device
2/ Modify the Root.plist
This will set what you want to display in your app settings - Inside your new Setting Bundle, right click on the Root.plist -> Open As -> Source Code
Copy Paste the Following code in it :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Title</key>
<string>About</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string></string>
<key>Key</key>
<string>version_preference</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>
3/ Create a Run Script
This will always get the version of your app from the Info.plist and display it in your app Settings
In the Newest Run Script section , Copy/Paste the following :
#Getting Current Version
VERSIONNUM=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
#Setting the version number in settings
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $VERSIONNUM" <YOUR-APP-NAME>/Settings.bundle/Root.plist
Just replace YOUR-APP-NAME by your app name