Where is the best place for... [iPhone] - iphone

In UIViewControllers I have several methods such as viewDidLoad, viewWillAppear, viewDidAppear, etc.
The question is: "what is the best place to, for example, set the background color of my view, instantiate, and set the background color of a UILabel, or instantiate an object that I set as #property in my class and things like that? "
Thanks!

So many questions at once!
The first time the view is loaded, in viewDidLoad you will already have access to all the readily initialized UI elements, so it is a great place to configure the view and to set your class properties.
If you come back to the view if it is already loaded (say, by popping a view from a navigation controller, or dismissing a modal view controller), viewDidLoad will not be called. Thus, if you want to change something (background, add a label, change the background of a label, etc.) based on something that might have happened since the view controller was initialized, you have to use viewWillAppear.
You would use viewDidAppear if you want to animate a change so the user can see it after the view has already become visible.
Edit: this is pertinent for if you use IB or storyboard. See CitronEvanescent's answer for the case that you create your view in code.

The feasible method would be viewDidLoad or -(id)init,-(id)initWithNibName constructors of the class.
viewWillAppear and viewDidAppear should be avoided,since you would not like to instantiate your variables again and again since they get called every time the view appears(from pop or tabSwitch).These two methods can be useful in case you want to change some variable values on reappearance

If you are creating your view programaticaly, you can set your properties on - (void) loadView this method will be call once before anything is displayed.
Generally i prefer instantiating the UI elements in the -(id) init and update their UI in loadView.
For further details : View construction reference

Related

iPhone - a UIView that behaves like a UIViewController

I need to create a class that will present a UIVIew and has a some code to initialize it before it is ready to show. I need to know when the view is ready, I mean, I need something like viewDidLoad or viewWillAppear, but as it is a UIVIew it lacks these protocols.
I cannot implement it as a UIViewController as I don't want to present it modal. It is really a rectangular view that needs to show on a screen side.
How do I declare this class? If the class is a UIView based I don't have the methods I mentioned.
thanks
Any reason to not do that kind of stuff inside the initWithFrame method on a UIView? Also, you can do additional stuff on layoutSubviews. A view controller has viewDidLoad because the view is lazy loaded (from a nib or otherwise - it also has a loadView). It has viewWillAppear and viewWillDisappear because it is managing the view (btw, even the view controller is managed by another view controller - these methods are called when you have the controller within a UINavigationController or UITabBarController or such classes which mange UIViewControllers. - the view itself is not really managing anything. All it knows about is how to draw itself. For that, you have layoutSubViews, drawRect, etc.
Doing some heavy stuff upon view's load will definitely kill the UI performance. You probably need to implement another kind of design pattern that will asynchrounously assign data values to the instance of your custom view - when that is done, you call layoutSubviews or setNeedsDisplay to update the view.
The scenario you described is no reason for not implementing a UIViewController. Assume you have a container view A and a subview B. Both have their own UIViewController AC and BC. Now on AC you add the View B managed by BC:
[self.view addSubview:BC.view];
You probably want to be using UIViewController.
You don't just have to present them modally. You can get your view controller's view with yourViewController.view, and add that as a subview of whatever view you want.
If you're targeting iOS 5, there are a few new methods (such as addChildViewController:) designed to make doing things like this easier. You can do it on iOS 4 too though, and it'll still work.
Implement a drawRect in youR UIView, plus an initialization flag. Just before the view is to be displayed the drawRect will be called. If the initialization flag isn't yet set, do your initialization and set the flag. This will only look good if your initialization can be done quickly (no long synchronous calls).
I need to create a class that will present a UIVIew and has a some code to initialize it before it is ready to show. I need to know when the view is ready, I mean, I need something like viewDidLoad or viewWillAppear, but as it is a UIVIew it lacks these protocols.
You might want to rethink how your view is being used. It sounds like you're trying to put too much controller-like logic into your view. That's why you're wanting your view to behave like a controller.
More specifically: What exactly are you trying to accomplish? If you're waiting for data to load before display the view, that might actually be something to put in the controller that is calling the view.
To illustrate my point, imagine you're putting some text in a UILabel that you read from disk. The reading from disk isn't really related to the view. The view only cares what text it displays, not how it received the text. Once it's read from disk, you can create a UILabel with that text that you read. This allows the UILabel to be more flexible.
That example might not be at all related to what you're doing, but I use it as an example of the difference between a view and a controller. Anything not related with the display and drawing of the view shouldn't belong there.

Best place to add shadow to view in viewController

I want to add a shadow (using the layer property of the view) to my view controller's view. Should I do this in load view after creating the view myself.
Or should I do this in ViewDidLoad.
EDIT: Currently I haven't implemented loadView.
The short answer is, if you're using loadView, it doesn't really matter whether you configure the shadow there or in viewDidLoad. viewDidLoad will be called right after loadView, in every case.
The longer version is that if in the future you decided to move your view creation into a XIB file, you would want to remove your implementation of loadView. In that case, you would need to customize the layer shadow in viewDidLoad. So theoretically you could save your future self some copy and paste work by putting it in viewDidLoad.
the loadView method is intended for view controller's view creation. So if you want to add shadow to it, then this would be the best place. And if you want to customize it's subviews, then it's better to do that in viewDidLoad

Do I programmatically add SubViews in ViewDidAppear, ViewDidLoad, ViewWillAppear, the constructor?

I'm trying to figure out from Apple's sketchy documentation which method is the best place to be initializing and adding my Views controls to the controller's view.
With winforms it's fairly straightforward, as they're always initialized inside InitializeDesigner, called in the constructor. I'm trying to match the reliability of this pattern if possible.
I'm working with UIViewControllers and UITableViewControllers inside a UINavigationController most of the time - if this effects it all.
Here's an example:
public MyController()
{
// Here?
AddViews();
}
public override ViewDidLoad()
{
base.ViewDidLoad();
// Or is should it be here?
AddViews();
}
public override ViewWillAppear(bool )
{
base.ViewWillAppear(animated);
// Here?
AddViews();
}
public override ViewDidAppear(bool animated)
{
base.ViewDidLoad(animated);
// Or maybe here?
AddViews();
}
void AddViews()
{
UILabel label = new UILabel();
label.Text = "Test";
label.Frame = new RectangleF(100,100,100,26);
View.AddSubView(label);
UIWebView webview = new UIWebView();
webview .Frame = new RectangleF(100,100,100,26);
View.AddSubView(webview);
}
I get mixed results with some UIControls when I add them to the view in different places. Visual lag sometimes, othertimes the webview is hidden somewhere.
Is there a general rule to keep to for adding them?
In general, this is what I do:
ViewDidLoad - Whenever I'm adding controls to a view that should appear together with the view, right away, I put it in the ViewDidLoad method. Basically this method is called whenever the view was loaded into memory. So for example, if my view is a form with 3 labels, I would add the labels here; the view will never exist without those forms.
ViewWillAppear: I use ViewWillAppear usually just to update the data on the form. So, for the example above, I would use this to actually load the data from my domain into the form. Creation of UIViews is fairly expensive, and you should avoid as much as possible doing that on the ViewWillAppear method, becuase when this gets called, it means that the iPhone is already ready to show the UIView to the user, and anything heavy you do here will impact performance in a very visible manner (like animations being delayed, etc).
ViewDidAppear: Finally, I use the ViewDidAppear to start off new threads to things that would take a long time to execute, like for example doing a webservice call to get extra data for the form above.The good thing is that because the view already exists and is being displayed to the user, you can show a nice "Waiting" message to the user while you get the data.
There are other tricks you can use, though. Lets say you want a UILabel to "fly" into the form after the form is loaded. In that case, I would add the label to the form in the ViewDidLoad but with a Frame outside of the view area, and then in the ViewDidAppear I would do the animation to fly it back into view.
Hope it helps.
Hmm, Apple's docs seem to be pretty clear, IMHO.
If you create your own root view (the root view of this particular controller's view hierarchy) programmatically, you should create it in -loadView without calling super and set the view property when done. If your view is loaded from a nib, you should not touch -loadView.
You add custom subviews to the view controller's view or otherwise modify it in -viewDidLoad. The recommended practice is to create your UILabel and UIWebView in -viewDidLoad and release them in -viewDidUnload, setting their references to nil if you need to keep them in ivars.
Note: -viewDidUnload is deprecated in iOS 6 and is just not called any more, because UIViewController no longer purges its view under memory pressure.
viewDidLoad relates to 'MEMORY', and viewWillAppear/viewDidAppear relates to 'APPEARANCE'. A view controller's view (which is a root-view of your view controller's views) can appear/disappear numerous times, even if the controller's view is already in memory.
(When referring to root-view, I also means its subviews, because the root-view has reference to its children (subviews), but from a view controller's perspective, it usually knows just the root-view. Reference to subviews can happens normally through view controller's outlets.)
The root-view itself MAY be removed from memory when there's a memory warning. The view controller will determine when is the best time to removed them from memory.
So, you would normally add subviews in viewDidLoad, because adding subviews means adding them to memory. BUT not if you create all of your views programmatically (not from a nib files). If that's the case then you should override loadView method, and create a root-view and add subviews there, so in this case you can omit viewDidLoad to add subviews.

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.

UIViewController vs. UIView - which one should create subviews?

I'm trying to wrap my head around the roles of UIViews and UIViewControllers. If I'm creating and inserting subviews programmatically, is it typical to do this from the view or the controller?
I'm really just wondering if there's a convention/pattern for this. In my sample application, I'm loading 50 images at runtime, adding them as subviews to the main view, then letting the user drag them around the screen. I'm currently doing all the initialization in the view's initWithCoder:
- (id)initWithCoder:(NSCoder*)coder
{
if (self = [super initWithCoder:coder]) {
// load UIImageViews and add them to the subview
}
return self;
}
The view also implements touchesBegan/touchesMoved to allow dragging. My problem comes when I try to access [self frame].size in initWithCoder, it doesn't seem to be initialized yet. This makes me think I may be loading the images in the wrong place...
It depends on what you're doing. If the view represents something "packaged", then you create subviews from the view itself. If you're merely aggregating views together, then you should do it from the view controller.
Think about traditional encapsulation. Is your subview conceptually "part" of its superview, or does it just live there in the drawing hierarchy?
Suppose you're creating a view that contains some controls, like to edit a record with multiple fields or something. Since you're going to be using those text fields and their data in the view controller, they conceptually "belong" to the view controller, and the parent view exists just for grouping and layout purposes. This is probably the more common scenario.
If you were creating a view subclass to behave like a new control, for example, then I would say you should create and manage the views entirely within the view class. I imagine this case will happen less frequently in practice.
It sounds like you may be adding them in the wrong place. If you moved the addition of the subviews into the ViewController, then you could do this work on viewDidLoad and you'd be guaranteed that the main view was already initialized and ready to access.
Dummy explanation would be like this:
Subclass UIViewController whenever you plan to display the view as modal (presentModalViewController) or inside UINavigationController (pushViewController)
Subclass UIView whenever it is a small component inside main view... for example you wish to do custom button or ...
More specifically in your example ... if you are initializing UIViewControllers you can set view's properties eg. like frame size only after your view is added to superview. Only
at that point UIViewController loads and initializes its view.
I think in your case you should use UIViews ... you can set frame size immediately after allocating&initializing them.