IF statment not checking condition on first run - iphone

I'm new to programming and I have an app that has a login view on start up and request the user to enter their name which is used throughout out the program. Once they enter their name and log in they are presented with the main menu view. Their name is saved using NSUserdefaults.
The idea is that they will only have to login once (or again if they logout) so they should only see the login view the first time they run the app however once the app is started again it still shows the login screen and also you have to press the login button twice before you are taken to the main menu.
I know that the app is storing the details because it is used thought the app but I cant work out why. Here is my code. If someone could help it would be greatly appreciated.
-(IBAction)LogInButton:(id)sender
{
NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserName"];
if(tempStr.length==0)
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:Name.text forKey:#"UserName"];
[prefs synchronize];
LogInView *Logview = [[LogInView alloc] initWithNibName:#"LogInView" bundle:nil];
[self presentModalViewController:Logview animated:YES];
}
else
{
MainMenuView *mainview = [[MainMenuView alloc] initWithNibName:#"MainMenuView" bundle:nil];
[self presentModalViewController:mainview animated:YES];
}
}

Judging by your description what you want is
On viewDidLoad check to see if the user is logged in
If YES show the MainMenu
If NO show the LogInView
The code may look like this
- (void)viewDidLoad
{
[super viewDidLoad];
[self showCorrectController];
}
The show correct controller method could look like this
- (void)showCorrectController
{
UIViewController *viewController = nil;
if ([self isLoggedIn]) {
viewController = [[MainMenuView alloc] init];
} else {
viewController = [[LogInView alloc] init];
}
[self presentModalViewController:viewController animated:YES];
[viewController release]; viewController = nil;
}
A convenience method is called isLoggedIn which looks like this
- (BOOL)isLoggedIn
{
// The double negation just means we get a boolean response
return !![[NSUserDefaults standardUserDefaults] objectForKey:#"UserName"];
}
Now edit your original method to something like this
-(IBAction)LogInButton:(id)sender
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:Name.text forKey:#"UserName"];
[prefs synchronize];
[self showCorrectController];
}
There are quite a few things that could be done to tidy this up a lot but this should be a start to get you going.
A word of caution on your naming of things. The convention is to start method and variable names with lowercased letters. Classes and constants start with uppercase letters.

It looks like the first time in:
The login screen shows up
The user presses login (and this method you're showing gets called)
The saved value isn't initially set, so this evaluates to true: if(tempStr.length==0)
You save the new value
You display another login screen
But I don't think you're showing all the code. What runs when the app launches?

Related

Objective c. Login user using storyboard

I have an storyboard with three view controllers, the init view with a button Init, the login view controller and the list view controller. When I click in the button init in the first view controller, I would like to verify whether the user logged in in order to switch to the login view or to the list view. How could I implement this using segues (segue conditionals??)
You could do something like this
BOOL isLoggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:#"isLoggedIn"];
NSString *headingStoryboardID = isLoggedIn ? #"YourAlreadyLoggedInVC_ID" : #"YourLoginVC_ID";
if([headingStoryboardID isEqualToString:#"YourAlreadyLoggedInVC_ID"]) {
AlreadyLoggedInClass *vc1 = (AlreadyLoggedInClass *)[self.storyboard instantiateViewControllerWithIdentifier:#"YourAlreadyLoggedInVC_ID"];
[self presentViewController:vc2 animated:YES completion:nil];
} else {
LoginViewController *vc2 = (LoginViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"YourLoginVC_ID"];
[self presentViewController:vc2 animated:YES completion:nil];
}
OBS: Ugly and uncompiled code but hope the concept gets across.
EDIT DUE TO COMMENT
To perform a push segue you call
[self.navigationController pushViewController:vc1 animated:YES];
instead.
You can Store your login value in user default when user login like this
in LOginViewController
-(void) doLogin
{
NSString * str = #"Loged In";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:str forKey:#"login"];
[defaults synchronize];
}
And in first view controller check whether this NSdefault value is nil or not.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userLogIn = [defaults objectForKey:#"login"];
if (userLogIn.length !=0) {
//then user Loged in
}else
{
//then user not Loged in
}
This code is just example you can change it acording to your need.

What is the perfect way to make a logout from IOS app?

The below code is working but has a bug. The scenario is that, I begin by logging in to enter the app system. Once the login has succeeded, the app will set UserDefaults (UserId). After that, I can navigate the app views with stored UserId. Once I go to settings and tab logout, that will clean UserId and go to login view.
The BUG: When I login again to the app and click the home button to go to iPhone desktop and close the app, and return to open it again it still storing the UserId. So, if I go to the setting and log out that will clean UserId and will not go to login view. I don't know why.
The code:
- (IBAction)resetKeychain:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Are you sure you want to logout?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Logout"
otherButtonTitles:nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex ==0) {
//logout
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
//delete user ID fro user Defaults
[defaults setObject:nil forKey:#"UserId"];
//redirect to login view
NewClassMoonAppDelegate * appsDelegate =[[UIApplication sharedApplication] delegate];
[appsDelegate.window addSubview:[appsDelegate.login view]];
}
}
From what I can interpret from you question, which needs to be formatted and made coherent by the way, I believe that:
a) your #"UserID" value is not syncing with NSUserDefaults because you are not calling the -synchronize method. NSUserDefaults will update its in-memory key-value store, but will not write it to disk meaning that it's lost at an arbitrary time.
b) The fact that it is not going to the loginView could be to do with any few reasons, most likely that it is already a subview of your UIWindow. So, instead of reusing the login property in your app delegate, create a new instance variable of the View Controller, and set that as the rootViewController instead.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:nil forKey:#"UserId"];
[defaults synchronize];
//redirect to login view
NewClassMoonAppDelegate * appsDelegate =[[UIApplication sharedApplication] delegate];
LoginViewController *login = [[LoginViewController alloc] initWithNibName...];
[appsDelegate.window setRootViewController:nil];
[appsDelegate.window setRootViewController:login];
}
}
Swift:
From max_'s answer with some changes:
let objectsToSave: [String] = [obj1, obj2, obj3]
for key in objectsToSave {
NSUserDefaults.standardUserDefaults().removeObjectForKey(key)
}
let appsDelegate = UIApplication.sharedApplication().delegate
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
let newLoginVC: LoginViewController = storyboard.instantiateInitialViewController() as! LoginViewController
appsDelegate?.window!!.rootViewController = nil
appsDelegate?.window!!.rootViewController = newLoginVC
EDIT: The only changes I've made are just that I initialize newLoginVC through Storyboards instead of initWitName.
Make property of UINavigation controller and synthesize it, And write below code on logout button
AppDelegate * appDelegateObj =[[UIApplication sharedApplication] delegate];
login *loginObj = [[login alloc]initWithNibName:#"login" bundle:nil];
[appDelegateObj.window setRootViewController:nil];
navObj=[[UINavigationController alloc]initWithRootViewController:loginObj];
[appDelegateObj.window setRootViewController:navObj];

UILabel becomes null after facebook login (UILabel dosen't update)

I am working on adding facebook SSO and the SDK to my project. All of my main facebook code is in my AppDelegate.m and AppDelegate.h.
In my view controller [[[UIApplication sharedApplication] delegate] performSelector:#selector(callLogin)]; is called when I press a button.
The callLogin method in my AppDelegate.m looks like this:
- (void)callLogin{
facebook = [[Facebook alloc] initWithAppId:#"XXXXX" 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];
}
}
Then in my - (void)fbDidLogin method I call the method setInfo which is located in my viewcontroller.
//this method is located in AppDelegate.m
- (void)fbDidLogin {
NSLog(#"FACEBOOK DID LOGIN");
ViewController * vc = [[ViewController alloc]init];
[vc setInfo];
}
Finally, here is my -(void)setInfo code which is located in ViewController.m
-(void)setInfo{
infoL.text = [NSString stringWithFormat: #"Connected to Facebook!"];
NSLog(#"%#",infoL);
//NSLog returns null
}
From setInfo I am unable to change the label and NSLog returns that infoL is null. I can update the label through methods like ViewDidLoad, but not setInfo.
What am I doing wrong and how can I fix this?
The view controller won't get updated because you just created some random instance of the class that is not on your navigation stack. I suppose you could call
[ self.viewController setInfo ]
assuming that is the property name for the vc you pushed on the stack in applicationDidFinishLaunchingWithOptions although this wouldn't be considered great design. Id factor Facebook delegate stuff out out app delegate, create a Facebook controller singleton class that your view controller can feed off
I assume that infoL represents a UILabel. Do you create this label in code or is an outlet that is created automatically?
If you create infoL in code, where is it allocated/initted? Is it non-nil at any time before your setInfo method runs?

Do we always needs to dismissModelViewController that we had presented?

I have Edited whole Question
What is the difference between presenting the ModelView Controller and dismissing the modal view controller in following situation??
HomeView
TableItemSelection View
PickerView
In HomeView
I am writing code in viewWillAppear to fetch values from NSUserDefault that is set from TableView. Below is my code for viewDidLoad (for initial values) and viewWillAppear(when new value from tableview)
- (void)viewDidLoad
{
[super viewDidLoad];
actionMinutes = #"0";
actionSeconds = #"0";
restMinutes = #"0";
restSeconds = #"0";
}
- (void) viewWillAppear:(BOOL)animated
{
actionMin = [actionMinutes intValue];
actionSec = [actionSeconds intValue];
restMin = [restMinutes intValue];
restSec = [restSeconds intValue];
NSLog(#"acMin:%d acSec:%d reMin:%d reSec:%d",actionMin,actionSec,restMin,restSec);
}
In TableItemSelection View
I am presenting this view from HomeView. Now i want to set value of NSString in HomeView based on Table's didSelectRowAtIndex Method. I am using NSUserDefault to set the value.
And with Done Button touch i am presenting HomeView. (Actually I have to dismissModalViewController) But when i use dismiss I am not able to get values in NSString of HomeView. I am getting values of the table from PickerView. (I am instructed to do that). Below is my code for Table view on DONE button touch
HomeView *homeView = [[HomeView alloc] init];
[homeView.view setBackgroundColor:[UIColor clearColor]];
[homeView.view setFrame:CGRectMake(0 ,40, 320, 460)];
homeView.actionMinutes = [[NSUserDefaults standardUserDefaults] valueForKey:#"actionMinute"];
homeView.actionSeconds = [[NSUserDefaults standardUserDefaults] valueForKey:#"actionSecond"];
homeView.restMinutes = [[NSUserDefaults standardUserDefaults] valueForKey:#"restMinute"];
homeView.restSeconds = [[NSUserDefaults standardUserDefaults] valueForKey:#"restSecond"];
homeView.song = [[NSUserDefaults standardUserDefaults] valueForKey:#"songstring"];
NSLog(#"%#",homeView.actionMinutes);
[self presentModalViewController:homeView animated:YES];
//[self dismissModalViewControllerAnimated:YES]; // if this method is used then no values are passed to HomeView
[homeView release];
In PickerView
I am fetching the values from pickerview and then store it in UserDefault.
below is my code for pickerview
NSUserDefaults *actionTime = [NSUserDefaults standardUserDefaults];
[actionTime setValue:min forKey:#"actionMinute"];
[actionTime setValue:sec forKey:#"actionSecond"];
So why exactly i am not able to get UserDefault values when dismissing ModelView.??? Does presenting a new view everytime will make a stack of views???
#DShah: Yes most definitely..!!
You need to dismiss every modal view.
Also Please post the code you are using.
Also keep in mind that you need to put the NSUserDefaults line first (the line which you use assign NSString value to NSUserDefaults) and then put the line where in you dismissModalViewControllerAnimated:.
If you require more help please leave me a comment.
Hope this helps you.
I think you are trying to store integer value in NSUserDefaults then you have to
Use setInteger:forKey: instead of setObject:forKey:. An integer is not an object, it's a primitive type.
To retrieve it use integerForKey:.
This is the final answer through which i am able to solve my problem
Here is a code on Done button touch event...
- (IBAction) btnDonePressed:(id)sender {
aurioTouchAppDelegate *appDelegate = (aurioTouchAppDelegate *) [[UIApplication sharedApplication] delegate];
appDelegate.homeView.actionMinutes = [[NSUserDefaults standardUserDefaults] valueForKey:#"actionMinute"];
appDelegate.homeView.actionSeconds = [[NSUserDefaults standardUserDefaults] valueForKey:#"actionSecond"];
appDelegate.homeView.restMinutes = [[NSUserDefaults standardUserDefaults] valueForKey:#"restMinute"];
appDelegate.homeView.restSeconds = [[NSUserDefaults standardUserDefaults] valueForKey:#"restSecond"];
// [self presentModalViewController:homeView animated:YES];
[self dismissModalViewControllerAnimated:YES]; // if this method is used then no values are passed to HomeView
}

Load an other View from applicationDidFinishLaunching in the AppDelegate

I have this code in my applicationDidFinishLaunching in the AppDelegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firsttime = [defaults stringForKey:#"firsttime"];
if (firsttime == nil) {
BenutzerdatenViewController *Benutzer = [[BenutzerdatenViewController alloc] initWithNibName:nil bundle:nil];
Benutzer.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[Benutzer release];
[defaults setObject:#"lasttime" forKey:#"firsttime"];}
else { [window addSubview:viewController.view];
[window makeKeyAndVisible];}
Always when I open the app the first time I just see a with "view" instead of the right view with buttons and so on. Where is the problem?
You need to add the actual view to your window. For firsttime, you need the following:
[window addSubview: Benutzer.view];
Also, don't release that viewController; you should store a reference to it somewhere.
In the other case (!firstime), it's unclear where you're getting viewController from; I assume it's a member variable.