Timing of Passing Variable between Two UIViewControllers - objective-c

Not sure how to ask this question so it will makes sense, but let me try. My app opens a UIViewController, and then calls another one. When it opens the other one it places a variable in a textfield successfully. When the user closes the 2nd UIViewController and returns to the 1st UIViewController, I pass back the variable and place it in a textfield. This is all successful at this point. The variable is being passed back and forth with no problems.
So here is what I am trying to do: upon returning to the 1st UIViewController I run a query statement which uses the variable in the textfield as a key to pull a record from a SQLite table. I use the NSLog to check the code and I see that the textfield is empty, but when the UIViewController appears the variable is in the textfield.
Are with me so far? I hope so…
I am running the query in the ViewDidLoad. I am thinking that the ViewDidLoad is running before it copies the variable from the 2nd into the textfield.
My main question is: should I be running my query statement in the ViewDidLoad or some please else to get the variable in the textfield. Basically, all I want to do is pull a record based on the value in the textfield upon returning from another UIViewController.
Thank You!

Technically, your viewDidLoad won't be called if your original view was never dealloced. The delegate methods that will be called are viewWillAppear: and viewDidAppear:.
You can pass the value from the second viewController back to the first one with a custom made delegate method. What you should keep in mind is that you should do the query with the NSString you pass back with the delegate method, and place it in the textField during viewWillAppear:.
Hope this helps!

viewDidLoad is only called when the view controller is loaded up from a nib. If you are switching back to one view controller from another, it won't be executed again. Try putting the code in viewWillAppear.

Related

How can I use a variable in two modal separated view's with the same class (.h and .m files)?

I am trying to use a variable (birthDateLabel) in two view controllers that are separated via a modal but use the same view controller class (CreateAccountViewController). The label works in the view that it is set in but after [self dismissViewControllerAnimated:YES completion:nil]; is run the varriable is reset, how can I retain it?
Order of operations:
The first instance of CreateAccountViewController is run
A button is tapped to go to a new instance of CreateAccountViewController but this instance has a different view with a UIDatePicker to set the birthDateLabel variable.
The birthDateLabel is set
The user taps done and dismissViewControllerAnimated is run
The app updates a UILabel on the first instance of CreateAccountViewController
Step 5 is what does not work, if I put the label on the view as the picker it works but when the modal is dismissed the variable is reset. How can I keep the variable set after the modal is dismissed? Or is my only option to create separate view controller classes?
I tried to do my best explaining this, but if you need me to explain it more just comment.
The standard way to do this is to use a delegate. The fact that your two controllers are both instances of the same class doesn't make any difference, other than they will both have a variable called birthDataLabel. The value of that variable is specific to each instance, just as it would be if these were of two different classes.
So, you should do it the right way, which is to create a delegate protocol in your second instance, and have the first one set itself as the delegate when it first presents the second one.
#rdelmar provides the most technically correct answer, but if it's just one value you could simply use nsuserdefaults. If the number begins to expand creating a delegate might be a smart choice.

How to call pickerView: didSelectRow: inComponent: without user interaction?

I have a 2 components, dependent pickerView. I have a preview UIImageView that changes each time the user uses the pickerView (and triggers the didSelectRow:inComponent:). This works just as I expected.
However, I want the pickerView to trigger didSelectRow: when the app launches, so that there is a Preview the moment the user sees the UIImageView. In viewDidLoad, when I try this:
[self pickerView:picker didSelectRow:row inComponent:component]; // row and component have 0 values.
next thing that happens - the pickerView shows up blank! Remove this line, and it works perfectly again. I tried this as well:
[picker selectRow: row inComponent:component animated:NO];
thinking that it will trigger didSelectRow: however it doesn't trigger it and my UIImageView remain blank.
Any advice on how to call the didSelectRow: method without the users help?
Update: by the way, the picker is inside another UIView (not the main one). In case it matters.
didSelectRow:... will only be called if a row has been selected by user interaction. If you select a row programmatically with selectRow:... then you have to add you own logic to update other components like the image view.
The principle is valid for many other delegate functions, such as e.g. tableView:didSelectRowAtIndexPath:.
Based on your comments, this what you are looking for then.
Does UIPickerView's selectRow:inComponent:animated: call pickerView:didSelectRow:inComponent:?
You have to manually call the didSelectRow method.

How to get selectedIndex of TabBarController, inside viewWillAppear?

I have code inside my viewWillAppear method that requires checking the tab bar's selectedIndex. The only problem is, at this point its too early for the program to return the index, so I'm getting null.
Is there a way to access the selectedIndex without having to put the code inside viewDidAppear? I'm trying to resolve a visible 1 second flicker/delay load, which seems to only work in viewWillAppear.
You have two ways to get it that I can think of. First, make the tabBarController a property of the appDelegate, and you can then get the appDelegate reference from the sharedApplication, then ask it for the UITabBarController object and ask it directly (or add a method to your appDelegate to provide the selectedIndex).
The second idea is to have a property on your viewController, just before its pushed (whatever) the selectedIndex is set.

ViewDidLoad and UINavigationController in iOS?

I have an app which is based on a UINavigationController. There is a menu screen with buttons that segue (push onto navigation controller stack) to one of 9 other "sub-screens". None of these sub-screens segue to any other screen. When a user is done inputing data on a "sub-screen" they can press a done button which will pop back to the original menu screen. (If you're having difficulty picturing this, imagine a tree like storyboard where there is one root ViewController and then 9 leaf viewControllers).
Ok, so with that setup I have a few questions about how viewDidLoad works.
~ First, is viewDidLoad supposed to be called every time we transition to a sub-screen. For example, suppose I go from the menu screen to sub-screen "B", back to the menu screen and then back to sub-screen "B". Should B's viewDidLoad method be called twice? If not, why might mine be getting called twice?
~ Second, assuming that it will get called each time, what do I do if I have a lot of long operations that need to be performed exactly one time for each sub-screen? Where should I put them (if I put them in viewDidLoad it would happen multiple times if the user kept going back and forth between this page and the menu)?
To answer your questions:
Yes, in general B's viewDidLoad method should be called each time that it is pushed onto the UINavigationController's stack. This is because each time that B is popped off of the stack it is typically released, and each time that you go to B a new instance of B is created.
There could be numerous ways to handle this type of situation. It is hard to tell what is right for you without seeing exactly what you are trying to do. One way would be to create a singleton object that handles the processing. The reason this might be better than handling it within your UIViewController is that a singleton can live throughout the lifetime of the application, whereas UIViewControllers typically have a relatively short lifespan. Singleton objects can be created just once and they can manage whatever operations and data that you need to persist through the lifetime of your application.
1.
viewDidLoad is called when the view is loaded, and viewWillAppear is called when the view becomes visible.
If your viewDidLoad is called several times that means that you are loading the view every time you are showing it and releasing it every time you are popping it. If you post some code I could help you identify the problem better.
What you could do is something like this:
In your "root" viewController class, declare each "leaf" ViewController as a member, lets say they are called leafController1, leafController2 etc and create retain-properties for them.
#interface YourRootViewController : UIViewController {
LeafController1Class *leafController1;
LeafController2Class *leafController2;
// ...
}
#property (nonatomic, retain) LeafController1Class *leafController1;
#property (nonatomic, retain) LeafController2Class *leafController2;
// ...
#end
In the ViewDidLoad of your top ViewController, init all the leaf-controllers using "initWithNibName" etc (or whatever you are doing to create them). Retain their instances like so:
self.leafController1 = [[[LeafController1Class alloc] initWithNibName:#"LeafController1NibName" bundle:nil] autorelease];
When the user presses a button, push the correct leaf to the navigationcontroller:
[myNavigationController pushViewController:leafController1 animated:YES];
When you pop the leaf controllers now, they will be kept in memory since you retained them.
This way your viewDidLoad will only be called once for each leaf, just as long as you always push the same instace of the viewcontroller to your navigationcontroller.
2.
Heavy code related to the view should be executed when the view has been loaded, i.e. triggered by viewDidLoad. But also it might be a good idea to keep other classes that hold info about your application which are not viewcontrollers and separate from the UI. Heavy computations is better made in the background, or when the app is loading for the first time.
viewWillAppear gets called every time the view appears. viewDidLoad ONLY gets called when the view is constructed - so for example after a view controller initFromNibNamed call when the view is accessed. viewWillAppear is called anytime your view controller was not in view but comes into view - so when your view controller is pushed, viewWillAppear is called. So you might think your viewDidLoad is being called twice, but in reality it's probably not. So you should put the methods in viewDidLoad. What are you doing that takes a long time?

Objective C Beginner: where to put code that needs to be executed once in UITableViewController

I have UITableViewController where I need to put initialization code only once to populate data source. in which method to put this code.
I tried with viewWillAppear: method, but it get executed every time view appear.
if you want to display things only once that the View has comed on screen, then yeah. go for it. Otherwise you also have ViewdidLoad or ViewWillAppear if you have to arrange things before the view begins the transition to slide in.
All of these methods will be executed every time from the tableView you tap on a row.
anyway the pattern you are trying to achieve is called singleton, you can find out about it more over here
What should my Objective-C singleton look like?
You can put it in viewDidLoad and it will be only once.
The - (void)viewDidLoad method is probably the place you want use. It gets called once the view controller has finished doing its loading code (either by loading a XIB or by calling loadView).