MVC when developing in objective-C without using the Interface Builder - iphone

What is the correct way of implementing true MVC in Objective-C (Cocoa/iPhone) when the view is NOT created with Interface Builder?
How do I best structure the code and tie the different components of the MVC pattern together when I'm not using the Interface Builder in my project?

Usually when you are trying to create a view without any help from a nib file, you will have to implement that view's controller's loadView method.
So my answer is, any stuff related to V goes to the loadView method in your controller's implementation, any other logic stuff related to C goes to the rest part of your controller's implementation.

It's really a matter of taste : some absolutely think that to one viewController you can have one and only one view so the only manner is to subclass UIView for every view. I totally accept that a viewController manages multiple sub view constituting a screen and I only subclass UIView where it make sense in term of reusability. In fact, I also accept that a viewController use multiple viewControllers to manage different isolated part of the view as does the UINavigationContoller for example.

Usually you create a subclass of the element you want to display. For instance a UITableView which you set in the init method. This way, you're ViewController just dequeues an instance of it

Related

Is it necessary to create a separate view class when using MVC?

After watching the Stanford iTunesU CS193p online course I have quick question regarding the correct way to implement an MVC design.
Usually when I do an application I set my view up as part of the controller and add UIButtons, UILabels etc. to that. Essentially the controller and the view become one, unless you count the UIObjects as being the view objects
In one of the early CS193p examples the tutor splits the view off from the controller as a separate object (subclassing UIView), before implementing a protocol and delegate property on the view which the controller object then conforms to.
I am just curious about the practicality of the CS193p design, I can understand that splitting off the view better represents the MVC design paradigm (especially as a teaching aid) but slightly sceptical of its application in real world applications.
Think about the "view" as objects such as UIButton and UIImageView; re-usable components that don't necessarily know anything about the rest of your application. Your view controller is the object responsible for configuring the view objects and managing their state.
There are times when you'll want to subclass UIView, mostly when you need to do custom drawing in drawRect:. You wouldn't subclass UIView to customize behavior though, that's what your view controller is for. For example, you wouldn't subclass UITableView and just to make the table view its own delegate. Instead you'd make your view controller the table view's delegate.
With iOS, the UIView class implements drawing refresh and touch handlers, not the view controller class. If you need drawRect: or touchesBegan:, etc., you will need a separate UIView subclass.
This partially could be because this is how buttons and labels themselves behave as well. They redraw themselves, and delegate processed touches. The view controller doesn't draw their content and track xy locations.
It's not strictly necessary. If you use Interface Builder, most of the reasons why you would build a custom view (breaking UI setup code out of your business code) are taken care of. However, if you want to build custom actions to your view, or setup some properties that you can't quite get at with IB, then it would make sense to split off your view into a separate class.

When to subclass UIViewController for custom subview?

I've seen custom subviews implemented as an UIViewController subclass, but that maybe could have been implemented as an UIView subclass.
When should I subclass UIViewController instead of UIView for a subview? Are there any drawbacks to subclassing UIViewController?
Personally, when I need some significant logic to go on, I do it with a UIViewController subclass. Also, if I am looking for some of the behavior that you get from UIViewController e.g. presenting it modally or in a navigation controller.
If you are doing something fairly simple or lightweight, a UIView subclass is usually enough. I seem to have used them most often when making custom buttons and table view cells.
In my experience I have found myself using more UIViewController subclasses than UIView subclasses, but this might not be the best, it just so happens that I feel a bit more comfortable using view controllers rather than straight-up views.
Take a look at what Apple has to say on Controller Objects and the MVC design pattern
In iOS controller are generally expected to fill at least one the following roles:
Coordinating controllers provide application specific logic. They respond to delegate messages, notifications, and IBActions. Coordinating controllers also setup connections between other objects and often manage the creation and destruction of those objects.
View controllers, specifically UIViewControllers, manage the display of one "screen" worth of content and trigger transitions to the next "screen". They respond to memory warnings and rotation events.
Mediating controllers exist in OS X but their role is usually filled by view controllers in iOS. They act as an intermediary between views and models; updating models when views receive input and updating views when models change.
If the behavior you are implementing fits into one of these categories you probably want to create a controller object. If your logic is only concerned with the display of data (and possibly responding to user input) then perhaps it belongs in the view layer. If your logic is about the data itself then it probably belongs in the model.
If you can't find a good fit for your logic in any of those layers then you probably should model it differently as a combination of different responsibilities which belong on different objects in different layers. ie a view which requests data to display from a mediating view controller.
You would also subclass the UIViewController if you're going to use an AdBannerView in your "view". AdBannerView needs a UIViewController to be able to work.
The thumb rule I follow is, If you are doing custom drawing, subclass UIView. Otherwise, subclass the UIViewController.

Custom UIView from Interface Builder

I'm trying to keep things organized and create hierarchy of views for my app.
So for instance I want to create a custom view to display some text, another custom view to display progress and then use all those views in the main view created with View-Based Application template.
I know how to create it programmatically - you create UIView subclass, implement drawRect method, place an empty UIView in Interface Builder and chance it's Class to my custom class. My problem is that I want to create those custom view's in Interface Builder instead programmatically.
So far I've created UIViewController controller with XIB file and in viewDidLoad method of view controller from the template I create that custom view controller instance and add it's view as a subview of that empty UIView added in Interface Builder (the same you would change Class in programmatic approach).
It works, but it's more of a hack for me and it's hard for me to believe that there isn't a better method where I could add those custom views in interface builder without having to implement viewDidLoad method and create controllers and add their views inside of that method.
This was originally a comment in Ratinho's thread, but grew too large.
Although my own experience concurs with everything mentioned here and above, there are some things that might ease your pain, or at least make things feel a little less hack-ish.
Derive all of your custom UIView classes from a common class, say EmbeddableView. Wrap all of the initWithCoder logic in this base class, using the Class identity (or an overloadable method) to determine the NIB to initialize from. This is still a hack, but your at least formalizing the interface rules and hiding the machinery.
Additionally, you could further enhance your Interface Builder experience by using "micro controller" classes that pair with your custom views to handle their delegate/action methods and bridge the gap with the main UIViewController through it's own delegation protocol. All of this can be wired together using connectors within Interface Builder.
The underlying UIViewController only needs to implement enough functionality to satisfy the "micro controller" delegation pattern.
You already have the details for adding the custom views by changing the class name and handling the nib loading. The "micro controllers" (if used) can just be NSObject derived classes added to the NIB as suggested here.
Although I've done all of these steps in isolated cases, I've never taken it all the way to this sort of formal solution, but with some planning it should be fairly reliable and robust.
For this to work, you have to create a plug-in for Interface Builder that uses your custom control's class. As soon as you create and install your plug-in, you will be able to add by drag and drop, instances of your view onto another window or view in Interface Builder. To learn about creating IB Plugins, see the Interface Builder Plug-In Programming Guide and the chapter on creating your own IB Palette controls from Aaron Hillegass's book, Cocoa Programming for Mac OS X.
Here is the link to the original author of the accepted answer to a similar question.
Maybe i didnt understand u?
you have library in the Interface builder u can move every component u want and place it on your view. (u can add another view by adding UIView and change its class name in the 4th tab).
then u declare vars with IBOutlet and connect them from the 2nd tab of ur file's owners to their components...another question?
Unfortunately, you can't do what you want to do with UIKit. IB Plugins only work for OS X, and Apple explicitly doesn't allow them for use with iOS development. Something to do with them not being static libraries. Who knows, they may change this someday, but I wouldn't hold your breath.

How do I set up several custom UIViewControllers under one central view controller programmatically?

Being new to Xcode and Objective-C I find it hard to get my head around the Interface builder and Objective-C when doing things that are following the basic pattern. I have created a subclass of UIViewController that I want to instantiate several times to make a grid with each row being controlled by an instance of this class. So there will be one root view controller (with navigation etc) that should include/genereate all the instances of the custom sub-viewcontroller.
Now what would be the best way to do this? All examples I can find are about navigation, where one view should replace another, but I want to have all the viewcontrollers visible on the same "page". Do I need to create a nib file for the custom controller at all? I have also been thinking about using the UITableView somehow but inserting my custom viewcontroller in every row.
Any help greatly appreciated!
Apple's documentation recommends using one view controller per screen. It is possible to decompose your interface and use multiple view controllers on one screen if you have a good reason to do it, but Apple hasn't really designed their frameworks to support this, so you'll run into pitfalls if you don't know what you're doing.
In this case, I question whether each row of your grid really needs its own view controller. I find it hard to imagine a case where this would be the best choice, although it's hard to say for sure without knowing more about your app. Some things to consider:
What is your custom controller doing? Is it mostly changing the visual appearance of its corresponding grid row? If so, perhaps it would be more appropriate to subclass the UIView itself.
If this object is really behaving as a controller and not a view, consider implementing it as a subclass of NSObject rather than subclassing UIViewController. The UIViewController for your screen can capture events and delegate them to the appropriate custom controller object, or your custom views can capture their own events and notify their associated controllers of those events directly using a delegate pattern.
If you're sure you have a valid reason to implement these objects as UIViewController subclasses, check out my answer to this question.

Why doesn't Apple allow subclassing of UINavigationController? And what are my alternatives to subclassing?

I'm currently building a tabbed iPhone application where each tab's view controller is an instance of UINavigationController, and where every subcontroller of every one of the UINavigationController instances is an instance of UITableViewController. Ideally, I'd like to subclass UINavigationController so that the controller for each tab is a subclass of UINavigationController that (in addition to having all the standard UINavigationController functionality, obviously) serves as the datasource and the delegate for each of the table views associated with its subcontrollers. Trying to do this seems to break the basic UINavigationController functionality in the subclass.
Seeing as Apple says in their iPhone documentation that one shouldn't subclass UINavigationController, and things seem to break when one does, I'm wondering how I should go about extending UINavigationController's functionality without subclassing, and generally speaking, how one should work around subclassing limitations when doing Cocoa development.
Thanks!
Why on earth do you want the UINavigationController to act as a datasource for the table? The whole point of UITableViewController is that you subclass it, and it acts as the datasource for the UITableView that it also places in, and fills, the parent view.
For reference, note that since iOS 6, UINavigationController can be subclassed legally.
This class is generally used as-is but may be subclassed in iOS 6 and later.
UINavigationController Class Reference
Of course, that doesn't mean you always should. But you can.
I'm going to go ahead and say your idea has some merit, if at every level you are truly using the same kind of data and each level perhaps has a different delegate to handle cell creation.
Basically there's no reason you cannot subclass UINavigation controller to add a totally orthogonal layer of data atop it, because it has nothing to do with the UI or behavior that UINavigationController is managing (which is what Apple is concerned you will be messing with). To those opposed to the idea, think of it as a per-tab data store that all pages in a tab can access instead of every page in the system having to go to the AppDelegate, or have a bunch of singletons. Well basically it's a singleton, but at least one that is already there and gets the reference passed around automatically.
All that said, I'll end with an alternate design proposal - I think what you are probably wanting to do is drill down through multiple layers reusing the same code to generate cells and such because you have the same kinds of data at each layer. A better approach to handle that is to have one view controller that you feed the subset of data to display, and when a user drills down it simply creates another instance of the same view controller with that new subset of data. That approach is much better than the idea of having the navigation controller act as a table delegate for each level, because you'd have to do a ton of rewiring moving back and forth and it would require even more work to remember scroll position at each level to boot. That's why you want to keep drill-downs using multiple instances of view controllers, but multiple instances doesn't have to mean multiple classes.
As I understand it, subclassing is not encouraged because Objective C allows a subclass too much access to the internal workings of its superclass.
The suggested alternative to writing a subclass is to write a delegate, in this case a UINavigationControllerDelegate. You can then encapsulate the specific behavior you want to extend into this delegate class, and link it up to the UINavigationController whenever you need it.
If the available controller heirarchy does not serve your needs in terms of handling data (my assumption, since we don't know why you want one object to be the datasource for multiple views), you can always create additional data and/or controller classes (subclasses of NSObject at least).
You can have a data or other object persist while changing views in various ways. (1) a property of your application delegate class. Any object in your app can get your app delegate instance with
[[UIApplication sharedApplication] delegate]
Use this sparingly since it's essentially creating globals.
(2) You can pass data or other objects from controller to controller as you push view controller subclasses or bring them up within tabs.
(3) Core Data is another way but requires a lot of Cocoa under your belt, and you still have to manage the context instance(s).
Because they want to avoid the UI inconsistency that plagues every other platform.