I am making a multiplayer game. My First screen , should show a login form (not modally). When it finishes, it should call a delegate to my "root class" and the "root class" should remove this view controller and add another.Then when the game ends the "root class" will be called with another delegate method and it should show another screen etc..
I have 3 ideas about it and I would like to know which is going to work better.
a) My root class is a uiviewcontroller and it adds/removes subviews when the delegate methods are called.
b) My root class is NSObject subclass and it changes the window rootViewControoler when it has to.
c) Navigation controller without navigation bar. But how i manage view hiearchy?
What is better logic to manage my view hieararchy? Any other idea than a and b?
Either a) or b) would work. The choice would depend on factors like the degree to which the model layer is used to determine the sequence of presentation of views. If the presentation sequence is dynamic, then the helper class design (your option b) may be purer in terms of MVC separation. Ultimately, the decision depends on the details and complexity of your application.
Generically, some of the questions I ask when making design decisions like this:
How does it affect memory management?
How will the design affect performance?
Does the design appropriately separate concerns?
Is the design flexible? Does it minimize dependencies?
Does the design take advantage of framework/platform design patterns?
Of the options you present, I like c) the best.
Option a) falls short because it ignores the primary rôle of view controllers - to manage full-page views of content. Using addSubview in situations like yours requires you to jump through a bunch of hurdles in order to manage the memory of all those objects in the view hierarchy, and you would just wind up reinventing the UIViewController wheel.
Option b) is ok, but somehow it never seems to satisfy me. Just swapping the root in and out willy-nilly seems risky - this is what UIViewController is made to do, and it will probably do it better than you or I could. At any rate, you lose any benefits of animation if you do this. Which brings us to...
Option c). UINavigationController is programmed to do the work required of your particular situation. You can manage the hierarchy using UINavigationController's - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated. You could do a normal push, but this will keep the previous VC in memory while your main game VC sits in front and demands resources from the system. In short, I think your c) is easy and effective.
As as post script here, be aware that there are alternatives other than your a,b,c. You might get by with using a UIPageViewController, though I'm not recommending it. iOS 5 introduced UIStoryboard as a method to manage your app's UI, and UIStoryboardSegue to manage transitions. Check out the docs, if you're targeting iOS 5, they might help you as well. But it sounds like a simple nav controller will work for you.
Related
I am developing an iOS 5 application with the following visual structure:
where each square is a separate view. The blue views will be created dynamically (their number, the subviews, the logic behind of responding to the events). I was wondering which approach is better:
Creating different instances of BlueViewController and adding them as child view controllers to the rootViewController or
simple adding different views to the view hierarchy without creating the BlueViewController class and manipulating the views directly via the rootViewController
What are the pros and cons of both approaches?
That depends entirely on what they do. If they are merely views then you should just be adding views to the view hierarchy. E.g. if they are just showing some sort of info, then all you need is a view. If you do it this way, I would still recommend that you use a custom UIView subclass that handles your yellow views inside them and the layout.
If however, you find that each of them need to be doing quite a bit of "controller logic" e.g. handling complex algorithms and calculations then you should implement them as controllers.
Hope this is of help to you :)
Well, both are possible solutions, with pros and cons, and the right choice depends on the behavior of your app.
Using BlueViewControllers requires more lines code, but I think it is the best solution if you want different behaviors and you like well organized approach.
On the other side, adding YellowViews directly to the rootViewController could be easier, especially if your app doesn't have many views and an elaborate architecture.
In general I prefer the first approach, because, even if your project doesn't require BlueViewControllers at the moment of its development, it should help with future updates.
Some of my UIViewControllers consist of several screens. I merged such each MVCs within one xib because the differences in screens were about 10% only (some different labels and buttons). The thing is I need to show concrete screen when pushing concrete UIViewController on screen. So, I have methods like "show screen1 and hide screen2" and "show screen2 and hide screen1" that I'm calling before pushing concrete UIViewController. Now, I know that having a separate MVC for separate screen would be more cleared but I'm a little bit annoyed about the duplicate stuff, so I'm taking an action to split only if there are major differences. How do you deal with such situations?
You don't have to have a separate MVC for every screen—that can get very messy! A controller can easily have multiple UIView outlets that you can hook up in IB and switch around as needed. Remember though, that MVC and other paradigms are a suggested design to make your life easier, not a law. You won't go to the 9th layer of programmer's hell for not using it—in the end, it's up to you. Use whatever makes sense for you and your app!
If I have a bunch of ViewControllers that are only ever going to deal with a single view, or even if my ViewController is going to deal with multiple views, why should I use another ViewControllers to manage the other ViewControllers? Why wouldn't I just change out ViewControllers at the ApplicationDelegate level?
Maybe I'm thinking about ViewController the wrong way? I'm used to writing in the MVC pattern with Ruby/.NET. For an example, if I were working with widgets I'd probably have a WidgetController and a List view, and a Detail view for the WidgetController.
What is the analogous iPhone MVC construction? I'd assume the WidgetController would subclass the ViewController and I'd have a couple different views depending on how I wanted to look at the widget data. Then, when I wanted to deal with Wodgits I'd make a WodgitController with its associated views and swap the window's subview out with the new Wodgit ViewController.
I don't see what having a RootViewController to control my controllers buys me. Where is the value? What am I missing?
I'll focus on one aspect: Compartmentalization is a very useful design principal. If you separate concerns and put things where they "belong", they will be easier to find, maintain, build upon, and co-opt for new purposes.
Consider this:
All the pipes in your house go to the same place. Do you urinate in your sink, or do you use the fixture designed for that purpose?
In the case of your app, the application delegate is responsible for responding to application events and managing universal application resources. The root view controller is responsible for managing your views and view controllers. As a view controller it has special abilities to do so with navigation control, the ability to present modal views, act as a delegate, etc. While you could create a view controller and manipulate it completely in the application delegate, the task will become exponentially more difficult as you multiply the number of views you are managing, especially if you wish to be a text field delegate, data source, etc. On the other hand, it is easy to split the root view controller into its own class. There is very little cost.
Why pee in the sink when the toilet is a step away?
I'm learning how to develop my own iPhone apps but I'm having a tough time understanding certain concepts.
First, am i right to say that for every view, there must be a view controller for it? And for every view controller, must there be a delegate for it?
Also, what is the role of mainWindow.nib? Most of the tutorials that i've read don't seem to touch that nib at all. What always happens is the setting up of a NavigationController as the root controller, which pushes another ViewController onto the stack and this ViewController will have another nib associated with it.
So can i assume that i can safely ignore the main window nib?
It's all about MVC (Model View Controller), innit?
The Model, well that's up to you - what does your app do? Think of it as the backend, the engine of your app, free of the cruft of font size decisions and touch events.
The View, Apple pretty much wrote that for you. You use their Textfields and tables and imageViews. You assemble them together using Interface Builder into your GUI (packaged as a .nib). You rarely, if ever need to subclass the standard view elements (in a game you want a custom View to draw to, as all your drawing is probably custom). You can break different parts of your GUI into different .nib files if this helps you manage them. It's entirely up to you.
The Controller, so you have probably got some work todo to enable your GUI to represent your model. You need Some Controllers. How many? However many is manageable by you. If you had a view containing 2 subviews would they each need a view controller? Nah, probably not. How complicated is your code to hook up the view to the model?
Some GUI patterns are so common that Apple even wrote the Controller code for you. EG the controller for a UINavigationBar, UINavigationController. So, if your app has hierarchical views that you need to navigate around and you need to display a navigation bar you can use an instance of UINavigationController instead of writing your own class. Yay!
Surely tho, the UINavigationController code (or any other viewController) can't magically know how to integrate with our model, with our view, can it? NO, it can't. In general in Cocoa if there is some class of object that mostly works off the shelf but also has optionally configurable behavoir - allowing us to tailor it to our needs - it is done by Delegation. ie Instead of subclassing UINavigationController we tell the specific instance of it where to find (for want of a better term) it's custom behavoir.
Why? Let's say you have a navigationController, a tableView and a textfield. UINavigationController mostly take care of your navigation needs but you have to have a crazy QUACK sound play each time the user moves to a new view. UITableView is mostly exactly everything you need from a table, EXCEPT you really want the third row in the table on the front page be twice the height of the other rows. And the standard, off -the-shelf UITextField pretty much takes care of your textfield needs EXCEPT you need your textfield to only be editable when the user is facing North. One way to handle this would be to create 3 new classes, a custom UINavigationController, a custom tableView and a custom textfield, and to use these instead. With delegation we could use the classes as they are and have one object be the delegate of all 3 instances - much cleaner.
Delegation is mostly optional, the docs will tell you when, and it's down to you and whether you need that custom behavoir.
I am trying to wrap my head around controllers in Cocoa Touch. The main problem is that I would like to have more than one controller “on screen” at once – I want to have a large view (with controller A) composed of smaller views controlled by their own controllers (say B). I’d like to have it this way because the division makes the code much cleaner. What’s bad is that the additional controllers (of type B) are not “first-class citizens” on the screen, for example they do not receive the autorotation queries and notifications. (And cannot easily display modal controllers, they have to send the presentModal… message to their parent controller.)
What is the difference between the A and B controllers from Cocoa viewpoint? Does the system keep some kind of pointer to the “frontmost controller”, a privileged one to which it sends notifications and such stuff? Why don’t the other controllers receive them, even though their views are on the screen? Is having multiple controllers “on screen” considered a hack? Or is it supported and I am just missing some point? Thank you.
More about the problem I am trying to solve: I am writing a simple photo browser. Photos are displayed in full screen, user can swipe left or right to change photos. The A controller takes care of the scrolling part and the B controllers take care of each photo itself.
Isolating B seemed like a good idea, since the photos are loaded from network and there is a lot that can happen, like the network might be down et cetera. In the B controller the code is fairly simple, since B only works with one particular photo. If I moved the code to the A controller, things would get messy.
The only thing I don’t like about the current solution is that I have to manually work around B not being a “first-class” controller. I have to pass some calls manually through A to B and when B wants to display a modal dialog, it has to send the presentModal… to A. Which is ugly.
There is now a first-class support for this scenario since iOS 5, it’s called controller containment.
swift controller containment
objc controller containment.
It's not closely related to the original question but important. Apple clearly states in View Controller Programming Guide that a view controller is responsible for controlling exactly one screen's content:
"Each custom view controller object you create is responsible for managing exactly one screen’s worth of content. The one-to-one correspondence between a view controller and a screen is a very important consideration in the design of your application. You should not use multiple custom view controllers to manage different portions of the same screen. Similarly, you should not use a single custom view controller object to manage multiple screens worth of content.
Note: If you want to divide a single screen into multiple areas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subsection of the screen. Then use a single view controller object to manage the generic controller objects. The view controller coordinates the overall screen interactions but forwards messages as needed to the generic controller objects it manages."
However in iPad Programming Guide they also say that there may be container view controllers:
"A view controller is responsible for a single view. Most of the time, a view controller’s view is expected to fill the entire span of the application window. In some cases, though, a view controller may be embedded inside another view controller (known as a container view controller) and presented along with other content. Navigation and tab bar controllers are examples of container view controllers."
Up to my current knowledge I would not use sub-view controllers in a view controller but try to subclass NSObject and send messages to them from my main view controller.
Also check this thread:
MGSplitViewController discussion
First, and this is important, view controllers don't get "on screen" -- views do. Your "top level" controller can certainly pass along the kinds of messages you're describing to its "sub-view-controllers". In fact, this is how most apps work. Consider an app that has a tab bar, and where the views use navigation controllers. You actually have several view controllers "running" at the same time, each with its own view on screen at once -- your "root" view controller will be an instance (or subclass) of UITabBarController, which then has several nested UINavigationControllers, each which will display nested view controllers (like an instance or a subclass of UITableViewController).
You might want to read up a bit on how responder chains work. Consider a touch event. It will be generated for the view closest to the top of the stack, that can receive events, which is also underneath the tap. If that view can't handle it, it gets passed up the view hierarchy food chain until something deals with it (and then eats it).
As to the specifics of your question, on the whole, I'm not sure exactly what the strategy you describe is really doing to benefit you in terms of complexity. It depends on how exactly you're implementing things, but having separate view controllers for each little subview may require more bookkeeping code than just having one view controller that knows about all its sub-view components.
This is a pretty old question, but since I guess there are people who might face the same problem today I'd like to share my solution.
I was writing this application that had this one screen with a lot of information, pagination, controls etc. Since according to Apple's MVC documentation on the role of ViewControllers, you should not implement the logic in view itself, or access the data model directly from it, I had to choose between having a Massive ViewController with a few thousand lines of code which was both hard to maintain and debug(even with unit tests) or find a new way.
My solution was to use UIContainerView like below:
this way, you can implement each part's logic in it's own ViewController, and the parent view controller takes care of constraints and sizing of the views.
Note: This answer is just a guide to show the way, you can find a good and detailed explanation on how it works and how to implement it HERE
Actually you can make it work earlier than iOS 5, since most of us are targeting 4.x and 5.x at the same time. I've created a solution that works in both, and it works great, few apps in appstore use it :) Read my article about this or just download and use a simple class that I've created for this purpose.