Saving a bool to NSdefaults on AppWillTerminate not working - nsuserdefaults

I am trying to logout a user when the application is terminated (since in this particular case the user data doesn't change very often there is no need to logout when going into background).
So here is my code:
- (void)applicationWillTerminate:(UIApplication *)application
{
User *user = [[User alloc]init];
[user logout];
}
I first tried to log the user out like so but it didn't work:
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"logged_in"];
}
Any ideas?

If you want the defaults to be updated immediately, you should sync after updating:
[[NSUserDefaults standardUserDefaults] synchronize];
As documented (khm, please look up the documentation), the NSUserDefaults class doesn't immediately persist the changes to disk, only once in a while.

Related

NSInvalidArgumentException in didreceivelocalnotifiaction

I am bit bit confused as why am I geting this NSInvalidArgumentException error as I am not doing anything special.Here is my code do let me if I have done anything wrong.Basically i am implementing the the Mixpanel analytics in didreceivelocalnotifiaction and sending the fire time to the mixpanel.I have stored the value for username.Please let me know why am I getting this error.Moreover its not regular,it comes once in a while so that is making more difficult to find the error.
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
// Handle the notificaton when the app is running
Mixpanel *mixp = [Mixpanel sharedInstance];
[mixp track:#"Notification Fired" properties:[NSDictionary dictionaryWithObject:notif.fireDate forKey:#"App Opens"]];
mixp.nameTag = [[NSUserDefaults standardUserDefaults] objectForKey:#"Username"];
[mixp identify:[[NSUserDefaults standardUserDefaults] objectForKey:#"Username"]];
}

how to disable re-login in iphone

I have developed an app which is related with signing in to an account and people can also get registered in my app, since those user info will be stored in a SQLite database.
The problem is that, when the user logs out of the account and then re-logs in, the app asks the user to login again. I dont want this to happen, as it should remember the user name and password and should login automatically.
Does anyone know how to get this done?
In your AppDelegate.m file , add the NSUserDefaults method ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if ([standardUserDefaults valueForKey:#"dbID"]==nil) {
[standardUserDefaults setObject:#"1" forKey:#"dbID"];
[standardUserDefaults synchronize];
}
}
and also you have sane the username and password save the NSUserDefaults.
and for log out functionality , add the code logout code where you want the logout the applications ...
-(IBAction)Logout :(id)sender {
[[NSUserDefaults standardUserDefaults] setObject:#"" forKey:#"dbID"];
[NSUserDefaults resetStandardUserDefaults];
}
in the login time check the dbID is null then user login with the username and password. if the dbID is not null the login the old username and password.
if u are exit the without logout the applications , then store the dbID is "1" in the NSUserDefaults and redirect the view controller and For save the user name and password in the your logon time...for save
[[NSUserDefaults standardUserDefaults] setValue:#"Your text field value" forKey:#"Username"];
[[NSUserDefaults standardUserDefaults] setValue:#"Your text field value" forKey:#"password"];
read the
NSString * _UserName = [[NSUserDefaults standardUserDefaults] stringForKey:#"Username"];
NSString * _password = [[NSUserDefaults standardUserDefaults] stringForKey:#"password"];
username and password save the NSUserDefaults is indicated the u have store the username and password in NSUserDefaults.
if the you have logout the application by button , the make the NUll username and password save the NSUserDefaults .. like
[[NSUserDefaults standardUserDefaults] setValue:#"" forKey:#"Username"];
[[NSUserDefaults standardUserDefaults] setValue:#"" forKey:#"password"];
Use NSUserDefaults. This one will work fine
NSUserDefaults *rememberDefault = [NSUserDefaults standardUserDefaults];
if ([[rememberDefault valueForKey:#"Autologin"] isEqualToString:#"Autologin_on"]) {
btnAutoLogin.selected =NO;
}else {
btnAutoLogin.selected =YES;
}
In your Button Action Method :
-(IBAction)btnOnOffSwitch:(UIButton *)sender{
if (sender.selected) {
sender.selected = NO;
}else {
sender.selected = YES;
}
}
and when you want to check use this:
NSUserDefaults *rememberDefault = [NSUserDefaults standardUserDefaults];
if([[rememberDefault valueForKey:#"Autologin"] isEqualToString:#"Autologin_on"])
{
write your code here. to push directly to your home screen. this should be checked in your login screen
}
may b this will help you.
for your condition when user successfully login first time at that time make 1 dictionary for storing username , password and user id else make 3 different nsuserdefault object for this 3 types.
and when user comes again in that login screen check that nsuser default value is empty or has some value so if the value is there than it has already logsin and u can directly redirect him to next page .. else display the login page..
here i have write only the logic not source code so u can try it out your self and learn more :)..
hope this will help you.

iOS Facebook SDK connect fails on iDevice

I'm using facebook connect in an iOS app (ARC, running on iOS 5). it was working fine on both simulator and device but since this morning it has stopped working on the device, it does still work on the simulator. On the device i get the fbDinNotLogin method called.
Now, I know the differece is simulator uses mobile facebook and my app uses native iOS facebook app, and I also know that you can tweak the facebook.m file to force the app to do the login elsewhere but I don't want to do that.
loading my previous builds from yesterday (where everything was working fine) also gives me the same results. so same code that ran yesterday doesn't run today. any idea why this happens? below is my delegate .m file:
[EIDT] I get various different behaiviours from the native facebook app. sometimes it opens facebook app, and stays there not coming back to my app. also sometimes it just goes back to my app quickly without allowing facebook app to ask me for my permission. I'm very confused. [/EDIT]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
user *userClass= [[user alloc] init];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// app already launched for the first time
}
else
{
// This is the first launch ever
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
[userClass CopyDbToDocumentsFolder];
}
facebook = [[Facebook alloc] initWithAppId:#"XXXXXXXXXX" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
return YES;
}
-(void)fbDidLogout
{
NSLog(#"Facebook loggedOut");
}
- (void)fbDidNotLogin:(BOOL)cancelled
{
NSLog(#"Facebook Connect Failed");
}
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void)fbSessionInvalidated
{
NSLog(#"Facebook Session Invalidated");
}
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt
{
NSLog(#"Facebook Toekn was extended");
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication: (NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Although the SDK attempts to refresh its access tokens when it makes API calls,
// it's a good practice to refresh the access token also when the app becomes active.
// This gives apps that seldom make api calls a higher chance of having a non expired
// access token.
[[self facebook] extendAccessTokenIfNeeded];
}
#end
Turned out the problem was indeed with facebook and not my app! my developer account had been failing to save changes etc, but it's back to a working now.

Is there any delegate that fires when I run the iphone application for the first time?

I need to track the download of a certain iphone application. I tried a lot and found out that we could track it from the AppStore. But i need to track that from my application itself. So please help me to identify the method that fires when the application starts for the first time. Thanks.
There's no specific method that fires only on the 1st application launch. You can set a flag in user defaults on application start - so if the flag is not present then that will mean that application launched for the 1st time:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
if (![[NSUserDefaults standardDefaults] boolForKey:#"AlreadyLaunched"]){
// First launch logic
[[NSUserDefaults standardDefaults] setBool:YES forKey:#"AlreadyLaunched"];
[[NSUserDefaults standardDefaults] synchronize];
}
...
}
But i need to track that from my application itself.
No.
But if you really want to do this you could use something like this:
BOOL hasUsedSpyWareFunctions = [[NSUserDefaults standardUserDefaults] boolForKey:#"SpyWareKey"];
if (!hasUsedSpyWareFunctions) {
[self spyOnUser];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SpyWareKey"];
}
if you are a Pro in spying you only set the key to YES if the method returned successfully (ie a network connection could be established)
There’s no such an event, at least not one that I know of. But what you want can be trivially done using NSUserDefaults. Simply check for some boolean flag and if it’s not there, it’s a first run and you can set the flag:
NSString *const AlreadyRunKey = #"already-run";
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (![prefs boolForKey:AlreadyRunKey]) {
[prefs setBool:YES forKey:AlreadyRunKey];
[prefs synchronize];
// do whatever else you want
}

Best way to check if an iPhone app is running for the first time

I want to check if my iPhone app is running for the first time. I can create a file in the documents folder and check that file to see if this is the first time the app is running, but I wanted to know if there is a better way to do this.
I like to use NSUserDefaults to store an indication of the the first run.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"])
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can then test for it later...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"firstRun"])
{
// do something or not...
}
Ok what confuses the hell out of me about User Defaults.
WHERE are they stored?
you dont care it varies per iOS/Mac.
you just getVALUE by KEY
setVALUE by KEY + synchronize
iOS/Mac does the rest.
This is the common use case:
Checking for the existence of a value e.g firstRun.
The first time it will NOT EXIST so usually followed by setting the value.
2nd Run
- on next loop it does exist and other use case/else stmt is triggered
---- .h
#interface MyAppDelegate : UIResponder <UIApplicationDelegate>
//flag to denote if this is first time the app is run
#property(nonatomic) BOOL firstRun;
------ .m
#implementation MyAppDelegate
#synthesize firstRun = _firstRun;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//==============
//Check to see if this is first time app is run by checking flag we set in the defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"]){
//flag doesnt exist then this IS the first run
self.firstRun = TRUE;
//store the flag so it exists the next time the app starts
[defaults setObject:[NSDate date] forKey:#"firstRun"];
}else{
//flag does exist so this ISNT the first run
self.firstRun = FALSE;
}
//call synchronize to save default - where its saved is managed by iOS - varies by device and iOS/Mac
[[NSUserDefaults standardUserDefaults] synchronize];
//TO TEST: delete the app on the device/simulator
//run it - should be the first run
//close it - make sure you kill it and its not just in the background else didFinishLaunchingWithOptions wont be called
//just applicationDidBecomeActive
//2nd run it should self.firstRun = FALSE;
//=============
//NOTE IMPORTANT IF YOURE ROOTVIEWCONTROLLER checks appDelegate.firstRun then make sure you do the check above BEFORE setting self.window.rootViewController here
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
---- USING THE FLAG
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.firstRun){
NSLog(#"IS FIRST RUN - Do something: e.g. set up password");
}else {
NSLog(#"FPMyMusicScreenViewController: IS NOT FIRST RUN - Prompt for password");
}
The examples above confused me a bit as they show how to check for it the first time but then mention how to 'check for it later' in the same comment.
The problem is when we find it doesnt exist we immediately create it and synchronize.
So checking for it late actually mean when you RESTART THE APP not in same run as first run.
In your app delegate register a default value:
NSDictionary *defaultsDict =
[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], #"FirstLaunch", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDict];
[defaultsDict release];
Then where you want to check it:
NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
if ([sharedDefaults boolForKey:#"FirstLaunch"]) {
//Do the stuff you want to do on first launch
[sharedDefaults setBool:NO forKey:#"FirstLaunch"];
[sharedDefaults synchronize];
}
You can implement it with the static method below. I think it's better since you can call this method as many times as you like, unlike the other solutions. enjoy: (Keep in mind that it's not thread-safe)
+ (BOOL)isFirstTime{
static BOOL flag=NO;
static BOOL result;
if(!flag){
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"hasLaunchedOnce"])
{
result=NO;
} else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
result=YES;
}
flag=YES;
}
return result;
}
You can use a custom category method isFirstLaunch with UIViewController+FirstLaunch.
- (BOOL)isFirstLaunch
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"kFirstLaunch"]) {
return YES;
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"kFirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
return NO;
}
}
And when you need to use it in controller
BOOL launched = [self isFirstLaunch];
if (launched) {
//if launched
}
else {
//if not launched
}
Use NSUserDefaults. If the sharedDefault has a key for your app, its run before. Of course, you'll have to have the app create at least one default entry the first time the app runs.
Swift:
var isFirstLaunch: Bool {
get {
if (NSUserDefaults.standardUserDefaults().objectForKey("firstLaunchDate") == nil) {
NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: "firstLaunchDate")
NSUserDefaults.standardUserDefaults().synchronize()
return true
}
return false
}
}
Another tip:
When using NSUserDefaults, these settings will be wiped if the app is ever deleted. If for some reason you require these settings to still hang around, you can store them in the Keychain.