Subview vs childViewController - objective-c

This is a general question but I'll ask it using a specific example to avoid confusion:
I'm developing an app that has a UIPickerView among other things on a single screen. I was wondering if it's appropriate the make a custom PickerViewController class to control my UIPickerView and then add my PickerViewController as a childVC...
OR should I just create an instance of UIPickerView in my existing VC and control it from there?
When should I do either of these options and what are the advantages of them?
Appreciate the help amigos.

If the UIPickerView is simoultaneously on the screen along with other UI elements, then you should just add it as a subview. The concept of a view controller is for when you start managing a completely different UI/window/set of elements (however you call it). If the picker view closely belongs to the functionality of the other elements, you should not create a separate view controller for it.

iOS 5.0 introduced the notion of child view controllers. Originally, any view controller except for UINavigationController and UITabBarController had to be modal and full screen. In iOS 5.0, you can now have several UIViewControllers present on one screen. This means that one UIViewController can have many children (UIViewController), where each child is responsible for controlling more specific views and models.

Related

Issues that can arise when using UIViews instead of UIViewControllers?

I've been trying to figure out what can go wrong when using UIViews instead of UIViewControllers and haven't been able to find any therefore I've been just using custom UIViews when generally UIViewController is recommended for some reason.
I prefer UIViews mainly because when custom animating for transitions they're easier to manipulate as far as I know. Correct me if I'm wrong.
Also, I customize everything on my own programmatically such as tab bar, navigation bar etc hence to me, a custom UIView does everything a UIViewController does..
So, is using a separate custom UIView instead of a new UIViewController problematic? If so, please enlighten me..!
Edit
I am aware of MVC model and by UIViews instead of UIViewControllers I mean ignoring the whole one UIViewController per screen thing and use UIView as a container for all objects for certain screens.
For example, when showing menu screen, instead of pulling a UIViewController up for its own "section", I just don't do UIViewController at all and do it with a custom UIView which works as a container, draw/add everything in there. The same goes for the rest of "sections".(settings, option etc etc)
Is this problematic?
I've been trying to figure out what can go wrong when using UIViews instead of UIViewControllers
You cannot do it generally, because view objects and view controller objects occupy different places in the Model-View-Controller hierarchy. They are not even one-to-one with each other, because a single controller often manages multiple views.
I prefer UIViews mainly because when custom animating for transitions they're easier to manipulate as far as I know.
In situations when a piece of functionality can reasonably go in either a view or in a view controller, it most likely belongs in the view, not in the view controller, so your observation is correct. Custom animation that can be encapsulated in a single UIView should be encapsulated in the UIView, even though the same code could go in a UIViewController as well.

What's the advantage of using UIViewController as owner of xib?

Most of the time, owners of xib is a UIViewController.
I sort of use it my self.
Still I am confused why.
I suppose, the viewDidLoad and viewWillAppear is kind of the main selling point.
Is that it?
What are the advantage of using UIViewController as owners of an XIB?
A UIViewController object is the main way for views to appear within an iOS window.
Apple provides this as a fundamental, foundational building block (along with so many others) which you can use to build upon quickly and get your app out to market.
And when you subclass UIViewController, you're able to do lots of beautiful customizations which can be collected and eventually turned into (hopefully decent) products. When you subclass a UIViewController, you need to set the "owner" of a XIB file to that subclassed view controller (e.g. ThioViewController), so that way the app knows what object (and user interface) is being instantiated.
Hopefully this isn't too super abstract of an explanation.
First, spend a bit time to understand MVC http://en.wikipedia.org/wiki/Model–view–controller
This is the milestone of Objective-C (not only) development.
UIViewController is controller for all your views (inside this viewController). It provide starting point for you to create views on the screen, manipulate the views, handle actions from views etc.
You can create UIViewController programmatically.
XIB is representation of the screen which you can comfortably operate in Interface Builder to create and customize design of your application screen or one of the screens.
Since XIB represent the screen(view) it must be the controller which controls all the view on the screen - UIViewController or UINavigationController or other type of controller depending of your needs.
Most of time you will subclass UIViewController and use it to achieve you goals.
UIViewController have several subclasses which inherit directly from it (UINavigationController, UITabBarController).
Also UIViewController hav several methods (some of them)
-(void)viewDidLoad
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
and
-(void)viewWillAppear:(BOOL)animated
Parameters
animated
If YES, the view is being added to the window using an animation.
Discussion
This method is called before the receiver’s view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call super at some point in your implementation.
Please check Apple documentation for more information
https://developer.apple.com/LIBRARY/IOS/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html

Putting an ADBannerView on top of a UINavigationController

I'm trying to put an iAd banner in an app that is based on a UINavigationController (it's not the standard nav-base app proposed by xcode, cause I don't need the table view).
I'd like to place an ADBanner on its bottom, to be always visible, no matter how the user pops and pushes views.
I studied the iAdSuite example in the apple sample code, but, though it's reported among the "best practices", I don't think it's the best practice for what I need. It basically declares an ADBannerView in the app delegate class and then implements the ADBannerViewDelegate methods for every single view the app needs. That means implementing the ADBannerViewDelegate methods over and over again on every view controller class you need! It doesn't seem too smart... :(
I'd rather prefer to have an approach more similar to what Apple itself does in the tab bar based app, where you have a part of the window always occupied by the tab controller and all the views switching above without affecting the tab bar view below.
You can't directly put an ADBannerView along with the nav controller in the app delegate, because ADBanner needs to be placed in a view controller (you get a runtime error otherwise).
I tried to subclass from UIViewController, implementing the ADBannerViewDelegate in this class, and place it in the rootViewController along with a UINavigationController but I'm not having good luck with this approach...
Has anybody found a good, simple way to to this? Any hint?
Thank you for any help...
You can have just one class for ADBannerViewDelegate, and just one instance of ADBanner itself. When the currently active view changes, remove ADBanner from the old view, add it as a subview to the new view.
EDIT:
to clarify, you don't need each view implement the ADBannerViewDelegate. You only should have one class implement it (that class doesn't have to be a view controller for that matter).
You would also need to maintain a somewhere a property that would point to the currently active view (e.g. you can update that property in your Navigation Controller's navigationController:didShowViewController:animated:, or come up with your own protocol for that if your views appear in a more complex way).
Then in your ADBannerViewDelegate you'd just resize the view currently pointed to by that current view property. The actual view doesn't even have to know it has an ad in it ;)

Is it wise to "nest" UIViewControllers inside other UIViewControllers like you would UIViews?

I've got a fairly complex view, for me anyway, that has a few "trays" with custom interface items on them. They slide in and out of my root view. I'd like to nest (addSubview) the items inside the view. Each needs some setup before being displayed...and none can be configured in IB (they're subclasses of UIView).
I'm wondering if it makes sense to subclass UIViewController for each "tray" and then have the VC's view property point to the "tray" view which I can populate with my custom UIView objects. This way I can leverage the viewDidLoad, etc... methods in UIViewController.
I'm not aware of others doing this - at least in the few samples I've looked at. It would create a situation where there would be multiple view controllers being displayed on the screen at once. from the Navigation controller itself on down to the rootViewController and its view and then any number (well, screen size permitting) of these small trayViewControllers. If so, how's the responder chain work? i assume it'd go from lowest UIView to its enclosing VC, then to that VC's parent view, then that view's VC, etc. etc. repeat, repeat.. up to UIApplication... am I asking for trouble?
OR, do I just stick with UIViews and adding subviews into subviews, etc. etc..
Prior to iOS 5.0 this will specifically not recommended because the nested view controllers' lifecycle events – viewWillAppear, etc. – won't be called. See Abusing UIViewControllers.
With multiple UIViewController’s views visible at once some of those controllers may not receive important messages like -viewWillAppear: or -didReceiveMemoryWarning. Additionally some of their properties like parentViewController and interfaceOrientation may not be set or updated as expected.
iOS 5.0 added containment UIViewControllers that correctly handles those lifecycle events by adding child view controllers.
- (void)addChildViewController:(UIViewController *)childController
I spent countless hours trying to get nested view controllers to work in iOS 4. I eventually did, but it required a lot of glue code that was easy to get wrong. Then I saw the warning in the docs.
I'm trying to do the same thing, but was dissuaded from your approach by Apple's documentation, which states that "You should not use view controllers to manage views that fill only a part of their window—that is, only part of the area defined by the application content rectangle. If you want to have an interface composed of several smaller views, embed them all in a single root view and manage that view with your view controller."
My experience on what you are trying to do has been a good one. I try to keep nib files as simple as possible, so I take any posible "subview" and encapsulate it in its own nib file with it's own view controller, therefore I end up having nested view controllers.
In one of my apps I have a very complex table view cell, that has a subview. So I ended up having a hierarchy that goes like this: the tableview controller on the top level, the tableviewcell's controllers for each row and inside each of these a subviewcontroller for the subview inside each cell.
And everything works fine.
Pardon my english.

When I open a custom UIView from a UITableViewController, how do I close the custom view and go back to the table view?

I'm using a UITableViewController for a menu in a game. The table view opens a a view controller for my custom UIView that shows the game. When the game finishes the UIView is notified (which is kinda ruining the MVC principals) and from there I am kinda lost.
Questions:
Can a UIView communicate with its controller? How?
Can one controller talk to the one that started it? How?
How do I transition between all of this complicated web of views and controllers gracefully?
Use a delegate protocol here. Your custom game UIView can use a delegate property and call methods on this delegate when events happen (game over, game paused, view closed, etc). Here's a great post on using delegates: How do I create delegates in Objective-C?
I'd recommend using a UINavigationController. You don't necessarily need to show the navigation bar, but if you nest your view controllers in a navigation controller you have access to -pushViewControllerAnimated: and -popViewControllerAnimated: which make it really easy to navigation between levels of nested view controllers.
Another benefit of UINavigationController - you'll get a nice slide animation when you switch between views.
There are other 3rd party mechanisms out there that you may prefer over the UIKit UINavigationController/UIViewController mechanisms. Check out the Three20 project, in particular the TTNavigationCenter class.