NSUserDefaults behaviour with app update - ios

I have a method in my iOS app that updates the application when detects when my server has a greater version for my app (a new ipa version). If the user wants to download it, the app updates itself on the iPad.
The thing is that I want to update some entities atributes from the DB when the app opens the new version for the first time, but i'm not sure how to. I can't debug it cause when I download the latest ipa, for XCode the app crashed.
I was thinking about doing something like this in the AppDelegate.m:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
//do the stuff i wanna do
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// This is the first launch ever
}
But I don't know if this [[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"] was set to YES before the update, cause the process should be:
1)Launch the app for the first time ever.
2)The app detects a newer version.
3)Download the same app -> At this point apple "replace" the older version to the newer one.
4)Open the newer version app.
5)Do the stuff i wanna do ONLY for the first time I launch the new version.

You could use an integer stored in NSUserDefaults with a version number hard-coded for each version of the app. If the integer is lower than the hard-coded version, prompt for updates:
NSInteger currentVersion = 3; // increment with each new version
if ([[NSUSerDefaults standardUserDefaults] integerForKey:#"HasLaunchedForVersion"] < currentVersion) {
[[NSUserDefaults standardUserDefaults] setInteger:currentVersion forKey:#"HasLaunchedForVersion"];
[[NSUserDefaults standardUserDefaults] synchronize];
// This is the first launch for this version
} else {
// App hasn't been updated since last launch
}

They will not be removed. And will have old values.
if "HasLaunchedOnce" is used in the old version. use a new one and call it "HasUpdateLaunchedOnce".
Check both values and decide what do you want to do.
if (HasLaunchedOnce exists && HasUpdateLaunchedOnce not exists)
// proceed

Related

How to differentiate between opening an iOS app after fresh install and after an update

I am implementing a feature to iOS app that have different behavior if the app is fresh installed or just updated from an older version
i.e. I need to show an alert to users who first open the app after updating it from an older version and not to show this alert to new users who installed a fresh copy of the latest version of the app
I used to know this information in other apps I did before by storing the version number and the build number into NSUserDefault but the case now is that I don't have this code in place.
So to do this I'll need to submit an extra build to Apple store, and even then I can only detect updating the app starting from this version but updating from older version to the next one will be counted as new install not update
So is the is any way I can get this information from the iOS?
Is there other NSUserDefaults your users have in your previous version that are mandatory for the app? You can use that as a workaround. If those exist, put up the alert, and add a new NSUserDefault key that the alert has been seen and not to display again. Otherwise set the setting to turn off the alert indefinitely.
But it's important to think of future releases going forward.
Try this:
//Detect installation.
NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *currentBuild = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSString *versionOfLastVersionRun = [[NSUserDefaults standardUserDefaults] objectForKey:#"VersionOfLastVersionRun"];
NSString *versionOfLastBuildRun = [[NSUserDefaults standardUserDefaults] objectForKey:#"VersionOfLastBuildRun"];
//Copy all the bundle JSON
if (versionOfLastVersionRun == nil) {
//Do something on first installation
} else if (![versionOfLastVersionRun isEqual:currentVersion]) {
//Do something if there is a new version
} else if (![versionOfLastBuildRun isEqual:currentBuild]) {
//Do something if there is a new build
}
//Save values.
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastVersionRun"];
[[NSUserDefaults standardUserDefaults] setObject:currentBuild forKey:#"VersionOfLastBuildRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
I hope this helps.
Happy coding.
EDIT
I have not sean that the question is marked as Swift, but I'm going to left this answer for someone in the future that maybe find this helpful.

How to check if current version of the app has launched before?

I'd like to show a user agreement / disclaimer the first time my iOS app is launched. Currently, I'm simply doing it with the following code in didFinishLaunchingWithOptions in the AppDelegate:
//Show disclaimer to user, if he never agreed to it yet
if(![[NSUserDefaults standardUserDefaults] boolForKey:kHasAgreedToDisclaimerKey])
[self showDisclaimer];
However, I need to show a new disclaimer every time a new version of the app is installed and launch for the first time.
One way I was thinking of solving this problem was by creating a different UserDefaults key for each app version, but that looks like it will leave a lot of junk keys on the user's device.
Is there a better way to solve this?
Close. Don't save something for each app version, just store the last opened app version and compare it to the current app version. Something like this:
//Get the last opened and current versions
NSString *lastOpenedV = [[NSUserDefaults standardUserDefaults] objectForKey:#"LastOpenedVersion"];
NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
//Show an alert if necessary
if (lastOpenedV == nil || ![lastOpenedV isEqualToString:currentVersion]) {
[self showDisclaimer];
//Update the last opened version
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"LastOpenedVersion"];
}
Sounds like you have the right idea.
I'd try something like this:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *storedVersion = [prefs objectForKey:#"AppVersion"];
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *bundleVersion = [infoDict objectForKey:#"CFBundleVersion"];
if (storedVersion) {
if (![storedVersion isEqualToString:bundleVersion]) {
[prefs setObject:bundleVersion forKey:#"AppVersion"];
[prefs synchronize];
// Show disclaimer
}
} else {
[prefs setObject:bundleVersion forKey:#"AppVersion"];
[prefs synchronize];
}
Basically, you are going to copy the bundle version to userDefaults, and compare it on every launch. If it isn't present in defaults, then you know the app was just installed, and you want to display the disclaimer. If it is in the defaults, then you want to check it against the bundle version. Anytime the bundle version doesn't match, you know the app has been updated.
Edit: Looks like took too long to mock up my example. I'm ten minutes too late, and you've found an answer. But I'll leave it here anyways :).
NSUserdefaults will be deleted when the app gets deleted, though data will persist on update. If that is OK for you, you could save a version number of the accepted version there, as mentioned by #Nick in the comment.
To make your information really persistant, write a version key to the keychain when the user accepted.

NSUserDefault with App Group is not working in iOS 8 Beta3

I have to save Boolean Value to NSUserDefault in my App with custom keyboard extension and share with App Group.
My Code is worked in iOS 8 Beta1.
self.defaults = [NSUserDefaults standardUserDefaults];
if([self.defaults boolForKey:#"BlackKey"])
{
NSLog(#"Black");
}
else
{
NSLog(#"White");
}
But Not in iOS 8 Beta3. When i retrieve Boolean value from NSUserDefault , it's return nothing and i can't load from custom keyboard extension.
I have also tried with initWithSuiteName in NSUserDefault. Am i only one for that problem or bugs of iOS 8 Beta3?
A few probable solutions are:
Your app group is not setup correctly, or you are not using the correct group identifier with initWithSuiteName:
You have not enabled network access for your keyboard. This document states the following when you have network access disabled for your keyboard (default behavior):
No shared container with containing app
It's a bug.
Try using
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"BlackKey"];
when you save and read it by using this code:
if([[NSUserDefaults standardUserDefaults] boolForKey:#"BlackKey"]) {
NSLog(#"Black");
}
else
{
NSLog(#"White");
}
or if you already done so, then it can be bug, and Xcode 6 beta versions also have other bugs so it's safer to try in Xcode 5 or older.

IPhone - One time setup screen [duplicate]

This question already has answers here:
Detect when an iOS app is launched for the first time? [closed]
(7 answers)
Closed 9 years ago.
I am developing an iphone app which ask for one time set up details like user name in the first two screens when the user launches the app for the first time. I dont want these 2 screens to come up when I am launching the app once the user has given the details.
I tried getting the info from internet but I was not able to how to find it out. May be I am missing the technical term or wordings involved in doing this. Could any one please help in accomplishing this scenario. Any sample code would be very helpful.
Thanks for your time
Just set a boolean variable to the user-defaults. The user-defaults is a way to save information to the phone, external from the application, that the app can call upon whenever you want.
Inside your app-delegate when it boots, check the user-defaults for a boolean.
To save a boolean to user-defaults:
NSValue *state = ... //Whatever state you want. NSValue allows for booleans.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:obj forKey:#"notFirstTimeRun"];
[defaults synchronize];
To load the boolean from user-defaults:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSValue *state = [defaults objectForKey:#"notFirstTimeRun"];
Do a check:
if ([state boolValue] == true){
//Has ran before, skip your UIViews or whatever
}
else{
//Has not ran before, do your setup or whatever.
}
What you are looking to do is basically store a flag that dictates whether the user has gone through the setup steps. And upon app launch, you check to see if that flag exists with the respective value to denote whether or not to show a setup screen. NSUserDefaults provides a really simple, easy way of persisting state across sessions.
How about setting a bool in AppDidFinishLaunching. You can check that bool everytime the app is launched and show or hide respective screen based on that.
This is how I would do it:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasBeenLaunched"]){
// This is not the first time, therefore open app as usual
} else {
// This is the first time, show special views
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasBeenLaunched"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}

is that possible to know my apps is first time run or not in xcode?

i create an apps that i want to prompt an message for the user.. maybe using UIAlertview. After that, if the user run the apps for the second time, the alert won't prompt up anymore.
is that possible? honestly i don't have any idea about how to doing this.
Any idea? I search on STO, actually this link, still confused.
what is NSUserDefaults? How can NSUserDefaults store this information? i mean this is my first time or second time.
thanks.
To know what's NSUserDefaults, I suggest to take a look the official doc.
And of course you can use it to fulfill your goal.
You use a user default to store information about the current amount of runs in the app.
More or less like:
BOOL isRunMoreThanOnce = [[NSUserDefaults standardUserDefaults] boolForKey:#"isRunMoreThanOnce"];
if(!isRunMoreThanOnce){
// Show the alert view
// Then set the first run flag
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isRunMoreThanOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Yes, U can save a value in NSUserDefault for the first time in your app & set it some other value once you open the app.
like
if(![[NSUserDefault standardUserDefault] objectforKey:#"AppOpenFirstTime"])
{
// App Open First time
// Show Alert
[[NSUserDefault standardUserDefault] setObject:#"1" forKey:#"AppOpenFirstTime"]
}
You can check if you stored some value in NSUserDefaults
NSString *flag = [[NSUserDefaults standardUserDefaults] stringForKey:#"not_first_run"];
if (!flag) {
//first run, do somethig
}
and then set it to some value
[[NSUserDefaults standardUserDefaults] setObject:#"just any string" forKey:#"not_first_run"];
NSUserDefaults is a key-value store saved between your application launches.
You can do it exactly as cortez said in your link. NSUserDefaults is written to disc, and will be created and accessed from your app.
See this link
First Time when your application launch at that time boolForKey:#"AlreadyRan" is FALSE. after that set it TRUE.
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"AlreadyRan"] )
{
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"AlreadyRan"];
}
With the NSUserDefaults class, you can save settings and properties
related to application or user data.
The objects will be saved in what is known as the iOS “defaults system”.
The iOS defaults system is available throughout all of the code in your app, and any data saved to the defaults system will persist through application sessions.This means that even if the user closes your application or reboots their phone, the saved data will still be available the next time they open the app!

Resources