Is there any official prohibition on subclassing uinavigationcontroller? It seems to me a risky thing to do, especially if Apple changes it.
There's no problem with sub-classing UINavigationController; I've done it on several occasions to provide functionality not supported by the delegate such as dependency injection in managed view controllers. Take a look at the delegate methods to see if they can accomplish what you need and if not, subclass on.
Related
I was left with continuing the code of a senior developer, where I came across a coding pattern that was not only bizarre, but got me curious about a lot of things. The pattern, however, that I spoke about had something like this:
There is a UIViewController the view of which has an instance of extended UIView attached to it as a subview.
This custom UIView class has a reference of the above-stated UIViewController.
There are a series of methods defined within the UIViewController that are responsible for handling events at the UIView.
Since this UIViewController exists as a reference, our custom view calls those event-handling methods through this reference!
In such a system of code, what are the memory implications? How is this any different from the delegate pattern? Under what circumstances using this sort of coding okay?
While this pattern is a little curious, I would hesitate to condemn this without more information about what this child view is doing and what it needs to inform the view controller about. There is, admittedly, a faint code smell here, and if I were to hazard a guess, I'd bet that this view is likely doing stuff that one would now generally put in a view controller.
Often, when adding a subview that has any significant complexity (or is likely to be reused in different views), one would consider an iOS 5 feature, "view controller containment" (see the Creating Custom Container View Controllers section of the View Controller Programming Guide or WWDC 2011 video Implementing UIViewController Containment).
If using storyboards, you can achieve much of this using the special "Container View" control introduced with iOS 6, found in Interface Builder's "Object Library" (in the bottom of the right panel in the standard Xcode layout). If doing this programmatically, just make sure to call the appropriate methods listed in the "Managing Child View Controllers in a Custom Container" section of the UIViewController Class Reference.
When using view controller containment, you have a parent view controller (the main view controller) and the child view controller (the view controller that is managing the subview). And in this scenario, it's very common to design a custom protocol by which a child view controller notifies its parent view controller of particular events. But rather than adding your own custom delegate property, you can use the built-in parentViewController property which is automatically populated when you adopt the above "view controller containment" pattern.
Having said all of this, I might let practical concerns drive whether the existing code base needs to be refactored or not. Perhaps the code predates iOS 5, but is a solid implementation of what we might have done back in the day. Bottom line, if it works, is otherwise well written, and has the delineation of responsibilities clearly defined, you might decide to just leave well enough alone. And if it's a little ambiguous (as the absence of a discussion of a protocol might suggest), perhaps just start by introducing a formal protocol between the child view and the view controller to make the interface explicit. Whether a more radical refactoring of the code (to use something like view controller containment) is called for is hard for us to advise on the basis of the limited information provided thus far.
I am using the UIViewControllerContainment feature in iOS. My container controller is called mainViewController. It consists of menuViewController and contentViewController. The menuViewController is a UITableViewController.
Now, I want that when I select a row in menuViewController I handle an event inside the mainViewController. I have to do all of this without changing the code of menuViewController.
** I am aware I can use delegates to call the mainViewController but using the delegate will alter ** the menuViewController code which I do not want to do.
Assuming that the menuViewController isn't designed with some sort of delegate or callback block (or you wouldn't be asking the question), you're options are really very limited, and there are no good options, since any option would violate the concept of containment that you're trying to take advantage of.
As I see it, your choices are:
Modify the menuVieController to add a delegate or block callback on item selection. This is the best approach since it keeps the menuViewController well contained and isolated.
Subclass the menuViewController, override didSelectCell... and do number 1. Probably need to make sure you call super as well. This is bad because you're making assumptions about the internal structure of menuViewController and violating containment.
Steal the tableView delegate and handle it yourself. This makes even more assumptions about the internals of menuViewController.
Bottom line, I'd really recommend you rethink the decision not to change menuViewController.
What I want
I want to add some logging code into my app without having to update all of my view controllers.
What I've tried
I attempted to add a category to UIViewController and override one of the delegate methods. However, this produced several warnings/errors.
Is there a way for me to inject code into all of my app's ViewControllers?
Look into method swizzling. It is a powerful tool and can save you a lot of time. Swizzle one of the methods you wish to have logs in, and then call the original method to have it do what it is originally supposed to.
You could subclass UIViewController and then add the logging methods in your super class. You would still need to touch all of your VC's though and change the class to your super class though.
You can't possibly have so many view controller classes in an iOS app that touching each one will be a huge problem. So create your own UIViewController subclass, maybe OurSuperViewController that'll act as a superclass for your view controllers, and add the logging there. Then modify each of your view controller classes so that they inherit from OurSuperViewController, and make sure that each one calls super in the relevant view controller methods.
Once you've done that, you can turn logging on or off at will by modifying just OurSuperViewController.
For an iPad app, I realize that having a UISplitViewController allows you to embed childViewControllers inside a parentViewController and the childViewControllers are able to control each of the left and right subviews. However, I was wondering if there is any intrinsic advantage to doing that versus just using a UIViewController that acts as the ViewController for the left and right subviews?
The main advantage to writing your own instead of using UISplitViewController is that you can customize it however you need. The built-in UISplitViewController can't be used as a child view controller, which may be a requirement depending on your app.
Keep in mind that if you don't need anything special, you should stick with what Apple has already provided. The less code you have to maintain, the better. Having said that, it actually doesn't take that much code to roll your own. My custom implementation is about 250 lines and features all the same delegate methods and even the presentation gestures (swipe right to show, swipe left/tap detail to hide).
However, I was wondering if there is any intrinsic advantage to doing that versus just using a UIViewController that acts as the ViewController for the left and right subviews?
You won't have to rewrite all the boilerplate code.
It's probably better designed and has less bugs than a quick hack whipped up manually.
The biggest advantage is going to be relying on a framework that has already been written and will probably be improved on in the future.
The split view controller went through a big upgrade between iOS5 and iOS6 with how the navigation side was displayed while the device is in portrait and if you used their framework its an automatic upgrade.
With that said if you wanted some custom look or functionality then it can be worth writing your own although breaking common behavior can be confusing to users depending on what you do.
I am a newbie, and I am wondering what a ViewController is. I've tried to look at the description, but I find it too complicated. I'm working on Xcode 3 and am trying to link two pages together.
Since you tagged this question with xcode3.2 i'll assume you're asking about UIViewController.
It's one of the UIKit Framework classes.
One of its most important properties is its view (which is an instance of UIView) that usually holds one or more subviews.
What differentiates it from simple UIView are its methods for memory management, handling appearance, implementation in UINavigationController hierarchy...
The dull information on UIViewController can be found here: UIViewController Class Reference
You're definetly want to take a look at View Controller Programming Guide for iOS and View Controller Catalog for iOS.