Application Design Question - objective-c

I have an application that uses a UITabBarController as its outer container. Each tab uses a UINavigationController for its root view controller. I employ a multi-button toolbar as the navigation bar's right bar button. Some of these toolbar buttons are universal to the application; some pertain to individual tabs.
My instinct is to create a base view controller class with all universal toolbar construction and implementation code, then have each of my root view controllers inherit from this base class. If they want to add additional buttons to the toolbar, they simply need to override the toolbar construction method (where I'll centralize the construction of the tool bar), and add the implementation code for the additional buttons.
Sounds good in theory, but since I'm new to Objective-C, I welcome any additional input/advice from more experienced developers.

If you have a enough reusable code in your "toolbar construction and implementation " to motivate you to implement a base class and reuse it on your child classes, then it actually sounds like a good solutions.
One thing that you should analyze is which class would you extend: UIViewController or UIToolBar.
If you just want a custom reusable toolbar that only changes some visual properties (like the label of a the left button, or let the right button visible or not, etc..), maybe the best approach is to implement a base class that extends from UIToolBar, and then use it in your view controllers.
But if you have a considerable complex logic handling actions from the buttons of the toolbar, or any "heavy code" beyond simple visual property settings, the creation of a base class that extends UIViewController sounds like a better approach.
The better choise is up to you and to what you want to implement/reuse.
Good luck!

Related

multiple view controllers strategy

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.

MVC practice regarding adding targets to UIButton on View

I have a question regarding best practices when adding targets to a UIButton on a custom view. Currently, I create my UIButton in a loadup method of my view, and assign my view as the buttons target. My view is handling logic when the button is pressed, and it occurs to me that this is not good MVC.
So, I'd rather have my controller provide itself as target and an action for the button, however I'm not sure the best way to accomplish this.
The view could be initialized with a reference to the controller, or could get the controller using UIResponder's nextresponder, and set the target with this reference. However, this could result in circular retains, and would require my view to be aware of the methods that exist on my controller, which is more tightly coupled than I'd prefer.
Alternatively, I could create a setter for each uibutton on my view. However, this quickly becomes unwieldy if I have several buttons, or a view that contains a custom subview with buttons. I could also create properties for each button, but that would also be unwieldy and allows the controller access to more than it needs (it just needs to set targets, it doesn't need to be able to get any reference to the button).
Finally, I could create and add targets to all my buttons within the controller, and pass it to the view on initialization, but that seems to violate the roles of MVC as well.
It seems as if this is a common scenario, are any of these practices considered standard, or is there a better solution?
My personal belief is that in Cocoa custom views are allowed to have logic and state needed for them to operate, but that they should fully encapsulate the logic and state. That is, you should expose an interface to subviews, but not the subviews themselves. You should expose any private properties or subviews through a combination of delegates and properties as well as custom actions.
That being said, given that you provided no specifics on the purpose of your custom view, it is difficult to provide specifics on the best approach.
It's proper to target the view that owns the buttons. This way, if you need to do any view manipulation (enable/disable, highlight, popup, etc) you're in the right place. Also, only the view will know what the button is, so that, in your action, if you want to check what is sender, you can do it. But having your controller know about each individual button would seem to be a more egregious violation of MVC.
It's not inappropriate to have an accessor for your buttons. It can be handy to have the reference around at runtime. If you don't use it, it's hard to argue that there's harm in keeping around an extra id. As for hiding them in a private interface, that's fine, but unless you're publishing your API or working with morons, I don't know what harm there is in making the accessors public.
It's proper for your view to have a weak reference to your controller, and the button actions can be as simple as invoking one of your controller's methods. It's no big deal, and if you want to add some logic a little later, there's a spot for it.
Sounds like you're doing fine.
PS This is stupid:

How do I add UITabBarController subview to UINavigationController

I am new to Objective-C and Cocoa and I am trying my way through some tutorials with some success. One task is troubling me. I am trying to create a root view controller that is a navigation controller as given by this tutorial:
http://fuelyourcoding.com/iphone-view-switching-tutorial/
On the second page that is pushed I would like the option to load a subview that is a TabBarController. Is this within iOS view guidelines. Is this possible? If so, could someone give some code snippets and explain necessary instantiations and connections in IB? Your help is appreciated in advance!
No, you should not push a UITabBarController to a UINavigationController stack.
Perhaps tell us what you're trying to accomplish and someone can suggest an alternative.
From Apple's View Controller Programming Guide - Tab Bar Controllers:
Note: Although a navigation controller
can be embedded inside a tab, the
reverse is not true. Presenting a tab
bar interface from within a navigation
interface is potentially confusing for
users. A navigation interface uses one
or more custom view controllers to
present an interface focused on one
goal, which is usually the management
of a specific type of data. By
contrast, the tabs of a tab bar
interface can reflect completely
different purposes in an application
and need not be related in any way. In
addition, pushing a tab bar controller
on a navigation stack would cause the
tabs to be displayed for that screen
only and not for any others.
I cannot answer your question directly, but in my app I have a UITabBarController which displays multiple UINavigationControllers and other types of controllers. So I think you may have it the wrong way around. In other words, create a project which uses a UITabbarController as the base controller and when you select a tab, load up the corresponding UINavigationController (or other type of controller) as necessary.

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 ;)

Should one use UIViewController in scenarios without UINavigationController?

Summary
From a conceptual point of view, should one be working with UIViewController subclasses and their Nibs, even if you're not using the UINavigationController?
Scenario
The application I'm trying to develop has no UINavigationController. I'm mostly looking at elements in one particular UIScrollView implementation, and if there's at all a 'next level of navigation', it merely alters the appearance of a small element to show more details. The detail views of the elements (different elements spawn different views) are laid out in Interface Builder, for which I opted to create new UIViewController subclasses with corresponding XIB files.
Doubt
While exploring the different ways I could have these instances animate into view, I come across a lot of solutions using the UINavigationController. The UIViewController itself already seems to be geared towards the synergy. There's a self.navigationController, and lot's of examples online of how to push and pop with and without animation.
Question
So what I'm wondering right now is "did I do the right thing?" Googling an answer to that question only brought me to more specific implementation examples, so I decided to post this.
Should I have restrained myself in using XCode's "new file" template for UIViewController subclasses with XIB? Or should I have implemented a UINavigationController in my app, even if there's no screenfulls of navigation going on?
I'd be much obliged for enlightenment.
Cheers,
Eric-Paul.
UIViewController is a useful tool. It offers memory management things, anchor points for interface rotation and lots more. If needed, they can be pushed to a navigation controller (if not now, maybe later), could be a page of a tab bar controller, or behave well in popovers on iPad.
They come cheap and I don't see a reason not to use them. And your code needs to go somewhere anyway. Don't flood the application delegate or the view.