Storing Last Launch - iphone

I am trying to store the last launch date of my app. So I did the following:
- (void)applicationWillResignActive:(UIApplication *)application {
NSDate *today = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:#"lastLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
However, when I relaunch the app again and print out the object for key lastLaunch it shows null. Why isn't it storing the date? Am I putting it in the wrong method? I am running it and terminating the app from Xcode.

applicationWillResignActive: is also called when you receive phone call...
You can find more info here:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/
I think that applicationDidEnterBackground is a better place to put your code because user can deny phone call and go back to your app...
And for iOS3 users without multitasking watch for applicationWillTerminate:
Stop in Xcode just kills your application without calling anything...

NSUserDefaults is weird in the iPhone simulator. I expect your code to work on an actual device.

Related

How can you detect if it is the first time a user opens an app [duplicate]

This question already has answers here:
How to get a "first time open"-view for my app?
(3 answers)
Closed 9 years ago.
Is it possible to detect if it is the first time a user opens an iOS application, using Objective-C?
I would like to show a welcome message when the user opens up the app for the first time, but not show it to them after that.
I'm looking for something like:
BOOL firstTime = [AppDelegate isFirstTimeOpeningApplication]
Look for some value in your app's preferences, or the existence of some file. If you don't find it, your app is running for the first time, so write the expected value to the preferences or create the file so that the next time your app runs you'll know that it's not the first time.
If you store the time and date of the first run instead of just a flag, you can determine how long it's been since the app was used. You might want your app to act like it's the first run if the user hasn't used your app in a very long time.
Note that this technique only works if the user hasn't deleted your app. When an app is deleted, all its data is removed. If you want to know if your app has ever run on that device before, even if it was deleted afterward, you'll need to record information to identify the device elsewhere, such as on your own server.
Use NSUserDefaults
//In applicationDidFinishLaunching:withOptions:
BOOL hasLaunchedBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"AppHasLaunchedBefore"];
if(!hasLaunchedBefore) {
//First launch
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"AppHasLaunchedBefore"];
}
else {
//Not first launch
}
Hope that helps!
You can save a "I've run before" flag in NSUserDefaults.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firsttime = [defaults stringForKey:#"firsttime"];
if (firsttime == nil) {
TheOtherViewController *Other = [[TheOtherViewController alloc] initWithNibName:nil bundle:nil];
Other.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[window addSubview: Other.view];
[defaults setObject:#"lasttime" forKey:#"firsttime"];
} else { [window addSubview:viewController.view];
[window makeKeyAndVisible];
}
}
Use NSUserDefaults to store a flag which will indicate if the user has launched the app before or not. If the value of flag .. lets say "IsFirstTimeLaunched" is false then it means the user has not launched the app before.

Detecting the initial launch of an app using NSUserDefaults

In reference to the following question: iPhone: How do I detect when an app is launched for the first time?
When I looked up NSUserDefaults apple reference, it said that registerDefaults does not store the data onto the disk. In the above question, the app registers the value firstLaunch to YES upon each launch. So each time the app is launched, firstLaunch is overwritten to YES and so the app will always think that this is the app's initial launch.
Am I right on this?
EDIT:
After doing what the tutorial above says, it doesn't always work anyway. I keep relaunching from Xcode and it keep printing out 1 bool value as in its the first launch.
registerDefaults: doesn't overwrite what is already in the defaults, but it sets defaults-for-the-defaults. So if a default is missing it uses a default-default. Confusing, isn't it?
If you've never written a value under the key FirstLaunch, then boolForKey:#"FirstLaunch" will use the value from registerDefaults:. However, if you did previously do setBool:NO forKey:#"FirstLaunch" and later ask for it again with boolForKey: then the value from registerDefaults: is not used.
registerDefaults: doesn't overwrite existing values, it only initializes values that aren't set to any value yet.
Try something like this in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if ([[[NSUserDefaults standardUserDefaults] valueForKey:#"firstRun"] intValue]==0) {
//do the stuff required at first launch
//after stuff done
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:1] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
NO first it will be nil then you set it to yes and before setting it to yes check if it's already set to yes or not. So first time userDefaults will return nil if you get something for a key. like
[[NSUserDefaults standardUserDefaults] valueForKey:#"FirstLaunch"];
will return nil on first launch of application.

NSUserDefaults not working on iPhone 4.0 device?

i am using NSUserDefaults to save data from the app and when the user leaves the app and then come back to it all the values are restored.
the thing is that it does save the values while the app is running in background mode. but when i close the app from multitasking and re-open it the app comes back as new with no values saved. i have added the methods beginInBackground and applicationWillterminate
but no help is their a new way of doing this on the new 4.0?
PS. i am testing on the device only. i could not use the simulator because i am using Map kit.
Are you calling the synchronize method?
In your applicationDidEnterBackground just use the following code:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults synchronize];
The problem you are having is that you are expecting an NSApplicationWillTerminateNotification that is not getting sent in 4.0 because NSApplicationDidEnterBackgroundNotification is getting sent instead. I have had the same problem. Register both notifications for your storage function and it will work again. You don't need conditional code since even if you register for a notification that does not exist in 3.0, it will never get called there so there will be no crash.
If you are not using notifications you can also override applicationDidEnterBackground: as noted in the above comment.

How to quit an iPhone app nicely?

or "How to simulate a home button pressed event?"
I need to restart my iPhone app, and I want the program to quit, so the user will only have to start it.
If I simply use exit(0) some changes won't get saved, as they would if the user quits by pressing the home button.
The restart needed for language change.
Related code:
- (void)onChangeLanguage: (id)sender {
NSArray *lang = [NSArray arrayWithObjects:((Whatever *)sender).newLanguage, nil];
[[NSUserDefaults standardUserDefaults] setObject:lang forKey:#"AppleLanguages"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults objectForKey:#"AppleLanguages"];
NSString *currentLanguage = [languages objectAtIndex:0];
NSLog(#"Current language: %#", currentLanguage);
// ***
}
If the user restarts using the home button, language will change.
If // *** is replaced by exit(0), the language won't change.
Calling exit(0) is the only legal (but highly not recommended) way to exit the program from your code.
As a possible workaround you can show UIAlertView with no buttons that cannot be dismissed (forcing user to quit your program manually) and telling the user that he has to do that to apply your changes.
I think it’s perfectly fine to call exit, just call [[NSUserDefaults standardUserDefaults] synchronize] before you do that. You can read about the synchronize method in the Apple Documentation:
Because this method is automatically
invoked at periodic intervals, use
this method only if you cannot wait
for the automatic synchronization (for
example, if your application is about
to exit) or if you want to update the
user defaults to what is on disk even
though you have not made any changes.
It's worth noting that there's a private API call, too. Of course, all the usual warnings about using private APIs apply.
[[UIApplication sharedApplication] terminate];

applicationWillTerminate works as long as I don't switch off the iPhone

to save some variables of my apps I use:
-(void)applicationWillTerminate:(UIApplication *)application {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setFloat: self.viewController.sLabel.contentOffset.y forKey:#"floatKey"];
[prefs setObject:self.viewController.newText forKey:#"stringVal"];
[prefs synchronize];
}
and to retrieve them, via a button, I do the following:
-(IBAction) riprendi:(id) sender {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
float myFloat = [prefs floatForKey:#"floatKey"];
//some actions here
}
Everything is working on the simulator. However, using it on a real iPhone, the variables' saving and retrieving works just if you press the Home button, exiting the app and opening again but NOT if you switch off/on the iPhone. In this case, the variables get simply lost once you re-open the app...
What am I missing?? This is actually driving me crazy :(
Thank you so much ;)
Fabio
If you mean hitting the lock button on the top of the phone by saying "switching on/off", then it won't work, because locking the phone does not cause an application to quit.
Your applicationWillTerminate: method is only called when you exit you're application to the home screen or to some other application. When the user presses the Sleep button, applicationWillResignActive: will be send to your application-delegate.
Apple's iPhone OS Programming Guide has a section on handling interruptions.
According to Apple's documentation
"NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value."
If you want to make sure things are saved you should call "synchronize" on your prefs.