multiple view controllers strategy - objective-c

I am making an app that has about 20 different view controllers that are loaded into a single container view. Some of the views have sliders and buttons and some have only buttons.
Is there a strategy I can use to make building the views controllers more inline with Objective C coding techniques?
Currently I am trying to combine similar methods into model objects but before I get too involved I thought I'd ask if there is a better way. I'm also willing to do the groundwork and research so any keywords to point me in the right direction would help, i.e. protocols, delegates, etc.

The main piece of advice I'd give you is to consider whether or not each one of those view objects needs to be controlled at all. Consider UIViewController like the delegate between the view and the model. If you don't need an extreme context switch (i.e. pushing a new view onto the navigation stack), then is it really advisable to have 20 delegates floating around? In most cases, not really. UIViewController is not a "heavy object" by any stretch of the imagination, but it can quickly make your codebase unwieldy and large if every time you decide to throw a new component onto the screen, you subclass UIViewController.
Try to focus your attention on dividing the logic to setup the view and the actual responsibilities of the controller (reacting to model changes, dispatching operations, updating the view) into a UIView subclass and a UIViewController subclass respectively. If you truly do need to keep some component of the view separate because its logic simply cannot fit under the main view controller's category of responsibilities, then, and only then, is a new view controller appropriate.

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.

The different of view controller and view in objective-c

I am new to Objective-c, I want to ask what is the different between view controller and view such as "UITableView" and "UITableViewController"?
What happen if I use UITableView instead of UITableViewController?
Thanks
You should look up the Model-View-Controller pattern in the Apple's documentation, since it is very important for using Cocoa. Basically, the idea in Model-View-Controller is a pattern for designing your class structure. Broadly, the model is where the application's data should be kept. The view is what controls the application's appearance and the controller is the place where the two are assembled. (Ideally, the view and the model classes do not even need to know about the other's existence).
Hence, the UITableView and UITableViewController are two different classes with two different purposes. The UITableView controls the appearance of the data and the UITableViewController "controls" the view (generally by passing it the correct data for display and layout). Since this pattern shows up again and again in Cocoa programming, you should take some time to become familiar with it.
They are two different things, they cannot be substituted for the other.
iOS follows the MVC design pattern, which stands for Model-View-Controller. The two classes you mention are 2 pieces of the overall puzzle.
The View is what gets displayed on the screen. That is its responsibility. So, the TableView is responsible for telling the phone what to render on the screen.
The View is also accompanied by the Controller. The controller decides what to do when something happens (user interaction, and other events that can happen at any time). So, the TableViewController is responsible for making the table do stuff (for example, telling the TableView what data to use for displaying on the screen).
So to sum it up, they are completely different, but they work very closely together in your application (you will almost always have 1 Controller for each View.
Well, the short answer is that one is the View and one is the Controller. Combine this with your data (the Model) and you have all the parts of MVC (Model - View - Controller).
Think of it this way, the UITableViewController controls the UITableview. They are complementary and they need each other to work.

Custom UIView as UITableView delegate and datasource?

I am writing a fairly complex iPad app - my first bigger one.
This app has some custom UIViews that present fairly complex data, including a table. These views do not take up the whole screen, and there can (and likely will) be many of them on screen at any time (though only one would be in an "expanded" state where the table is shown).
Here's a basic example that should convey the basic principle:
Please note that these things are not supposed to be in popovers; instead, the FamilyViews expand to show their detailed data. (And please also note that this mockup was only created for the sake of this question and has little to do with how my interface is going to look; I know this is not good screen design)
I'm undecided on who to put as the delegate and datasource of these custom views:
Making the ViewController for the current screen delegate and datasource is unelegant, because it's not just one table that's part of the VC's main view.
Making the View itself the delegate and datasource seems a bit weird to me because it feels like giving the view too active a role; making it into a half-controller.
Making the underlying model object the datasource seems too tightly coupled, and also breaks MVC. And it doesn't answer the question of who should be the delegate.
I'm tending towards making each of these "FamilyViews" delegate and datasource for their own tables. Action on these tables will have to be coupled to the FamilyView's delegate (the ViewController), but that shouldn't be a problem, should it?
Anyone have some input on this?
Views should know how to paint themselves and layout their sub views, depending on their properties, and that's it.
You definitely should let a controller class be the delegate instead of the view itself.
The delegate controller doesn't have to be the view controller that displays the view, though. It could easily be a completely separate controller class that only knows how to handle what the view requires.

Are modal view controllers the preferred way to replace the entire interface on an iPad?

Specifically, I have something like a game, with a menu screen made out of standard components. I want a button to switch to another view controller that the user will interact with for a while, then return to the menu screen. It seems like having the menu controller present the 'game' mode as a modal view controller is the most straightforward solution, but is this the best way to essentially replace the entire view? Is the whole menu (which may later become a deep nav or split controller) kept in memory as long as the modal controller is in front, and is this something I should bother to worry about?
There are really two parts to this question:
Which method of transitioning from one view to the next in an iPad application provides the best experience to the user?
Which method of transitioning from one view to the next is easiest to implement and best handles memory management?
I'm not going to try to address the first part of this question other than to point you to Apple's 'iPad Human Interface Guidelines' which says (among other things):
Reduce Full-Screen Transitions
Closely associate visual transitions with the content that’s changing. Instead of swapping in a whole new screen when some embedded information changes, try to update only the areas of the user interface that need it. As a general rule, prefer transitioning individual views and objects, not the screen. In most cases, flipping the entire screen is not recommended.
When you perform fewer full-screen transitions, your application has greater visual stability, which helps people keep track of where they are in their task. You can use UI elements such as split view and popover to lessen the need for full-screen transitions.
http://developer.apple.com/library/ios/prerelease/#documentation/General/Conceptual/iPadHIG/DesignGuidelines/DesignGuidelines.html
However, in your case I'd have thought a full-screen transition is entirely appropriate (but then I'm not a user experience expert).
In answer to the second part, yes displaying a new view controller modally seems like a good approach to take.
By default both the objects used by the menu view and those used by the modal view will be kept in memory - but the great thing about using UIViewController sub-classes is that they've got some default memory management built-in. If your application receives a memory warning whilst the modal view is being presented in full-screen mode, the menu view controller's views will be removed and it's 'viewDidUnload' method will be called. So in your implementation of this method you should release any objects you don't need and then recreate them as needed in the menu view controller's viewDidLoad method (which will be called again before the menu view is shown).
This is explained in more detail in the UIViewController class reference:
When a low-memory warning occurs, the UIViewController class purges its views if it knows it can reload or recreate them again later. If this happens, it also calls the viewDidUnload method to give your code a chance to relinquish ownership of any objects that are associated with your view hierarchy, including objects loaded with the nib file, objects created in your viewDidLoad method, and objects created lazily at runtime and added to the view hierarchy. Typically, if your view controller contains outlets (properties or raw variables that contain the IBOutlet keyword), you should use the viewDidUnload method to relinquish ownership of those outlets or any other view-related data that you no longer need.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

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.