When to put into viewWillAppear and when to put into viewDidLoad? - iphone

I get used to put either of viewWillAppear and viewDidLoad, it's OK until know. However I'm thinking there should be some rules that guide when to put into viewWillAppear and when to put into viewDidLoad?

Simple rule I use is this. viewDidLoad is when the view's resources are loaded. The view is not drawn onscreen yet. So calculations and code dealing with the geometry and visuals of the view should not be put here. They should be in the viewWillAppear or viewDidAppear method.
Also viewWillAppear can be called multiple times
When a popover/modal view is displayed and remove
When an alert view/actionsheet/uiactivityController's view is displayed and removed.
For these reason, viewWillAppear should not contain codes that takes longer to finish. (at least the code running on the main thread). Neither should codes that only needs to be run once per view display.
There are more I am sure but these are simple to remember and I hope it helps.

viewDidLoad: Alerts you that a view has finished loading
viewWillAppear: Runs just before the view loads
viewDidLoad is things you have to do once. viewWillAppear gets called every time the view appears. You should do things that you only have to do once in viewDidLoad - like setting your UILabel texts. However, you may want to modify a specific part of the view every time the user gets to view it, e.g. the iPod application scrolls the lyrics back to the top every time you go to the "Now Playing" view.
However, when you are loading things from a server, you also have to think about latency. If you pack all of your network communication into viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of your app. It may be good idea to first show the user an unpopulated view with an activity indicator of some sort. When you are done with your networking, which may take a second or two (or may even fail - who knows?), you can populate the view with your data. Good examples on how this could be done can be seen in various twitter clients. For example, when you view the author detail page in Twitterrific, the view only says "Loading..." until the network queries have completed.

Related

Good design for having an ActivityIndicator across entire app

I have the need for an activity indicator view in my app when different views are loading and when data is being retrieved. The problem is the mainVC (where I would place the indicator) is not always aware of when processing is happening so it can start the indicator but it cannot stop it.
e.g. the mainVC loads and then programatically adds a new VC - this VC in turn asks a model to retrieve - it displays data etc. So this newly added VC actually knows when processing is finished and it does not have access to the indicator view (although the indicator is visible at the top).
I was thinking of using notifications - is this the best way of handling this situation?
I'd recommend looking at the brilliant MBProgressHUD library:
https://github.com/matej/MBProgressHUD
It's a very simple set of classes you can use to display loading and progress views that can be accessed by all view controllers in your app. Basically, you can set it up in your app delegate and add it to your app window.
Every view controller can then access the progress view from the delegate and show/hide it when required. It comes with an example project and code - it's very easy to use and customise.
Notifications are one half of the solution. You have to combine them with a persistent object so that you can also get the current state at all times. E.g., when a view controller is about to appear, it needs to read the initial "downloading" state from somewhere, because the VC might have been created after the "start" or "end" notification was sent.
Then, while the VC is alive, it can simply respond to notifications to update the indicator.
This design is particulary important for views, which run the risk of getting unloaded/reloaded all the time.

(iphone) pushViewController in background thread?

IPhone SDK - Leaking Memory with performSelectorInBackground
seems to suggest you can actually pushViewController in background thread.
But I get a warning from stackoverflow people that I shouldn't do this.
eg. (iphone) start timer from background thread?
is pushViewController considered "UI updating"?
(because I know that UI updating should be done in main thread only)
If it is so,
when a viewController takes a while to load, and want to show an indicator while loading.
What is my option?
Couple of strategies here.
1) BEFORE you do the push, but at the point you know you are going to do it, bring up a suitable activity view on the current view. I do this in some apps where you click on a row in a table but the pushed view has to do some web comms that takes time, so I leave the table cell highlighted in blue and add a white spinner to the left of the disclosure indicator. Works well.
2) Use lazy loading to get the new view controller on screen quickly, but defer the heavy code until after it has loaded so that the new controller can look after it's own activity view. By lazy loading I mean you should do as little as possible in the init method and make careful use of viewdidload / viewwillappear / viewdidappear etc to spread the work out and get an activity view on screen as soon as you can.

iOs: When should I initialize upcoming controllers (UIImagePickerController) from a view?

Suppose I have a navigation controller where the next action is to take a picture or select an image from the library.
If I initialize UIImagePickerController during didSelectRowAtIndexPath:, (I believe) the response will be a little slower as the controller needs to initialized. Also, if the user cancels and opens again, it would reinstantiate that controller every time.
However, if I create the controller during viewDidLoad: of the navigation controller, it takes up memory while the user is on that view. Side questions: Does this, however, slow down the loading time of the navigation?
Or should it be done in an NSOperation when the view is loaded?
Overall, what would be the best place to load the ImagePicker?
I'd lazy load the controller when it first gets called (in didSelectRowAtIndexPath) so it wouldn't have to be reloaded every time, and not worry about initialization time.
It seems that in your case you will always need an image picker on didSelectRowAtIndexPath. You can load it on the view and customize (camera, cameraroll, etc.) and present on the row selection. Probably it doesn't matter that much. UIImagePickerController presentation is very slow anyway, especially with the camera.
I don't recommend an NSOperation for this task.

IPhone - Which View Controller methods to use

I'm trying to figure out what logic should go into the different UIViewController methods like viewDidLoad, viewDidAppear, viewWillAppear, ...
The structure of my app is that I have a root view controller that doesn't really have a view of its own, rather it has a tab view controller and loads other view controllers into it. But in the future, it may have to load other view controllers instead of the tab bar controller depending on app logic.
My main question is, what do people usually put into the viewDidLoad, .... methods.
Currently I:
viewDidLoad - setup the tab bar controller and set its view to the view controller's own view
viewDidAppear - check if user has stored login info
if not - present with login
if so, login and get app data for first tab
I'm trying to figure out now if my logic for setting up my tab bar controller should go into loadView rather than viewDidLoad.
Any help would be great. Small examples found on the web are great, but they don't go into detail on how larger apps should be structured.
You should not implement both -viewDidLoad and -loadView; they are for different purposes. If you load a NIB, you should implement -viewDidLoad to perform any functions that need to be done after loading the NIB. Wiring up the tabbar is appropriate there if you haven't already done it in the NIB.
-loadView should be implemented if you do not use a NIB, and should construct the view.
-viewWillAppear is called immediately before you come onscreen. This is a good place to set up notification observations, update your data based on model classes that have changed since you were last on screen, and otherwise get your act together before the user sees you. You should not perform any animations here. You're not on the screen; you can't animate. I see a lot of animation glitches due to this mistake. It kind of works, but it looks weird.
-viewDidAppear is called after you come onscreen. This is where you do any entry animations (sliding up a modal, for instance; not that you should do that very often, but I was just looking at some code that did).
-viewWillDisappear is called right before you go offscreen. This is where you can do any leaving animations (including unselecting tableview cells and the like).
-viewDidDisappar is called after you're offscreen (and the animations have finished). Tear down any observations here, free up memory if possible, go to sleep as best you can.
I touch on setting up and tearing down observations here. I go into that in more depth in View controllers and notifications.
viewDidLoad will be called once per lifetime of each UIViewController's view. You put stuff in there that needs to be set up and working before the user starts interacting with the view.
viewDidAppear is called whenever the view has appeared to the user. It could potentially be called more than once. An example would be the root screen of an app using a UINavigationController to push and pop a hierarchy of views. Put stuff in there that you'd want done every time. For example, you might want to hide the UINavigationBar of the root screen, but show it for all subscreens, so you'd do the hiding of the bar here.
Therefore, you'd put your logic for setting up your UITabBarController in viewDidLoad, since it only should be done once.
Regarding your app, is there a reason why you don't just make the UITabViewController be the controller loaded by your app delegate? It seems that you have a level of indirection in your app that you may or may not need. It's probably better to simplify it now, and refactor later if you need something more complex.

Why UITableView methods are being called before viewWillAppear?

I was looking forward to find a cause for my application being crushed at some point and I found out that methods of UITableView are being called before or at the same time as viewWillAppear is called.
In viewWillAppear I have code that is initializing number of rows in each section but numberOfRowsInSection is being called before I finished setting up array that has amount of rows in each section.
I believe that viewDidLoad is not suitable in my case because it is being called only once after launching an application. Am I right? And I need to make my initialization function called each time a view appears on the screen.
How can I overcome this failure?
Thank you in advance.
Well, I think this 'problem' has to do with that there are multiple threads running taking care of the view and the UITableView.
The view calling this view could (before switching to this view) call a method on the View which gathers the data.
User pushed button
You fire a method on the destination view, gathering information
Switch to view
You could work with delegates to know when the destination view is ready loading the data you needed, so you can switch to that view then.
Hope this helps.
I think the right answer is that "[super viewWillAppear:animated]" will call UITableView's method.So it is necessary to put this code after the code that initialize the tableView.