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
}
Related
My other question was ambiguous so I will make this one clearer. I have a table view on one viewController and when a cell is selected, it saves a number to NSUserDefaults. On my main viewController, I retrieve this number and want to update a label with it. I did some debugging and found that when I go back to my main viewController from the tableView one, this is the order at what happens:
1) main view loads
2) tableView cell tap recognized
3) number saved to NSUserDefaults
How would I change the order so that the main view loads last so that when I click a cell, it changes the label in my main viewController?
Here is the code from my didSelectRow method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *pointsPath = [[NSString alloc] initWithFormat:#"totalPoints"];
NSString *numberFirst = [[NSString alloc] initWithFormat:#"numberFirst"];
int totalPoints = [[NSUserDefaults standardUserDefaults] integerForKey: pointsPath];
int number = [[NSUserDefaults standardUserDefaults] integerForKey:numberFirst];
if([indexPath row] == 1)
{
NSLog(#"Selected First row");
if(totalPoints < 10)
{
if (number != 0)
{
NSLog(#"Did not add a point, but saved");
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:numberFirst];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else if (number == 0)
{
NSLog(#"Added a Point");
int newPoints = totalPoints + 1;
[[NSUserDefaults standardUserDefaults] setInteger:newPoints forKey: pointsPath];
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:numberFirst];
[[NSUserDefaults standardUserDefaults] synchronize];
int logPoints = [[NSUserDefaults standardUserDefaults]integerForKey:pointsPath];
NSLog(#"Point Count:%i", logPoints);
}
}
A controller's view is loaded on demand. So the thing that triggers viewDidLoad is somebody else performing controller.view. If you've already pushed the view controller into a container view or otherwise started to present it then that'll be the agent responsible.
viewDidLoad, and under iOS 5 and below viewDidUnload, are intended to give you the hooks you need if you want to create some part of the view programmatically.
If what you're doing is trying to account for a setting that may have been changed while the controller wasn't visible, you should probably use viewWillAppear:. That's the intended way to determine when you're about to transition from invisible to visible.
If you wanted a completely active link between the two things then you would set up the view controller that displays the number to listen for NSUserDefaultsDidChangeNotification and to update views as necessary when that occurs.
Guys i finally found the problem if anyone has this problem... You need to make sure that when the user selects a cell, it is a push segue not a modal... This is so frustrating that is was so simple!!
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.
Say for example if I have two buttons one for apples and one for orange, and I select apples and takes me to the apples screen. How can I make it for now on every time I run the app it will go to the apples screen?
in viewDidLoad
if([[NSUserDefaults standardUserDefaults] objectForKey:#"fruit"] != nil)
{
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"fruit"]isEqualToString:#"apple"]) {
[self.navigationController pushViewController:appleVC animated:NO];
}
else{
[self.navigationController pushViewController:orangeVC animated:NO];
}
}
and on Button Methods
on Apple button
[[NSUserDefaults standardUserDefaults] setObject:#"apple" forKey:#"fruit"];
on Orange button
[[NSUserDefaults standardUserDefaults] setObject:#"orange" forKey:#"fruit"];
You can store information like this using NSUserDefaults.
You'd store a boolean bAppleSelected like this:
NSUserDefaults * standardUserDefaults = [NSUserDefaults standardUserDefaults];
[standardUserDefaults setBool:bAppleSelected forKey=#"appleSelected"];
You can read it by accessing the default userDefaults:
BOOL bApple = [standardUserDefaults boolForKey=#"appleSelected"];
On your app delegate you must have some method that instantiates the very first controller and displays it in a window. You can just create an "apples controller" and push it there
You can use NSUserdefaults here,
NSString* fruit=#"apple";
[[NSUserDefaults standardUserDefaults]setObject:fruit forKey:#"controllerName"];
[[NSUserDefaults standardUserDefaults]synchronize];
and insted of the name string of your firstview controller in appdelegate file use the above NSUserDefaults.
The following code is my latest attempt to display a view controller when my application receives a particular local notification:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
NSLog(#"Notification Received. UserInfo: %#", [notification.userInfo valueForKey:#"notificationType"]);
if ([[notification.userInfo valueForKey:#"notificationType"] isEqualToString:#"backup"])
{
NSLog(#"Backup notification received.");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"Yes" forKey:#"shouldBackup"];
[defaults synchronize];
SettingsViewController *vc = [self.window.rootViewController.tabBarController.viewControllers objectAtIndex:3];
[self.window.rootViewController.tabBarController.navigationController pushViewController:vc animated:NO];
}
else
{
NSLog(#"Did receive notification: %#, set for date:%# .", notification.alertBody, notification.fireDate);
}
}
I then have this piece of code which I use in the viewDidAppear method to determine wether or not to perform the backup:
if ([[defaults objectForKey:#"shouldBackup"] isEqualToString:#"Yes"]){
[defaults setObject:#"No" forKey:#"shouldBackup"];
[defaults synchronize];
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Backing Up Your Data..";
HUD.minSize = CGSizeMake(135.f, 135.f);
[HUD showWhileExecuting:#selector(performBackup) onTarget:self withObject:nil animated:YES];
}
However, it appears that viewDidAppear is never called, can anyone explain what it is I'm doing wrong? I've tried several different approaches now and I just can't seem to get it to work..
Thanks,
Tysin
You need to push the SettingsViewController onto the stack from a NavigationController in order for its delegate methods to be called (in this case viewDidAppear). It seems that your root view controller is a TabBarController. In this case add the UINavigationControllerDelegate to your root VC, more info on what to do next can be found here http://www.touchthatfruit.com/viewwillappear-and-viewdidappear-not-being-ca
Also, are you sure viewDidAppear is not getting called or just the code within it is not getting called? Add a breakpoint to find out.
Lastly, do you haveĀ [super viewDidAppear:animated]; in the viewDidAppear method of SettingsViewController?
If all else fails you can always call viewDidAppear manually from the parent view controller :)
Hope this helps!
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?