access UINavigationController from subclass of UINavigationBar - iphone

I have a UINavigationBar subclass, is it possible someway from that UINavigationBar to get my UINavigationController?

This is not a good design pattern. You should put the navigation logic into your view controllers. If you have controls (such as buttons) in your custom navigation bar, you should also handle these events in your view controllers.
Note that the UINavigationBar does not deal with the controllers (it should be the other way round), rather it deals with the UINavigationItems, which will look different according to if they are on top of the navigation stack or not.
There is a trick to make your custom navigation bar the navigationBar property of your view controller's navigation controller. Normally this is a read-only property. But you can put it into your navigation controller in Interface Builder in Xcode, and then change the class name in the inspector to your custom class. You will then be able to refer to your bar with the usual self.navigationController.navigationBar from within your view controller.

Related

How do I add a Navigation Bar to a UITableViewController in Interface Builder?

Interface builder does not let me click and drag a Navigation Bar onto a Table View Controller!!! It is super frustrating.
All I want is a table view with an edit button (done in interface-builder). If this is not possible, then how do I add a navbar progammatically?
From the outline view, make sure your Table View Controller is selected.
Then go to the Editor menu, and click on the Embed In submenu, and choose Navigation Controller and voila. You have your navigation controller pointing to your tableview controller with a relationship built in.
For a table view with an edit button at the top, use a UINavigationController, with a UITableView as the rootView. That means you're going to make a custom UITableView subclass for your table view, and use that as the rootView of your UINavigationController instance. (Programatically, it's set with UINavigationController's -(id)initWithRootViewController. It's also settable through IB.)
Then, in your UITableView subclass, uncomment the following line:
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
and voilà, your UINavigationController's view shows up as a table view with an edit button on the right side of the navigation bar.
Since the controller is at the top of the stack, there's no "back" button on the left, so you can use self.navigationItem.leftBarButtonItem for whatever UIBarButtonItem you create.
I agree that it's difficult to figure out how to do things like this in Interface Builder, but luckily it is possible to add a Navigation Bar and Bar Button Item to a Table View this way. Here's how to do it:
Drag a blank View (an instance of UIView) from the Library to the area near the top of the Table View. As you drag near the target area, Interface Builder will highlight it in blue to show you where to drop the View. Let go, and the View will be added as a subview of the Table View's header view.
Drag a Navigation Bar from the Library and drop it on the blank View you just added.
Drag a Bar Button Item from the Library and drop it onto the Navigation Bar.
EDIT
The problem with the above approach is that, as Bogatyr points out, the Navigation Bar will then scroll along with the Table View. Apple recommends using a custom subclass of UIViewController that owns both the Navigation Bar and an instance of UITableView resized to fit. Unfortunately, that means you would have to implement the UITableViewController behavior needed by your UIViewController subclass yourself.
Another approach that seems to work well is to create a custom subclass of UIViewController that owns a blank background view containing the Navigation Bar as well as a blank content view (an instance of UIView) that fits under the Navigation Bar. Your custom subclass would have an outlet pointing to an instance of UITableViewController in the same nib file.
This has the advantage of allowing all the view components to be created and configured in Interface Builder, and doesn't require implementing UITableViewController methods from scratch. The only detail you'd need to take care of in the Table View Controller's parent would be to add Table View as a subview of the parent's content view in viewDidLoad.
The parent could implement the action methods for the Navigation Bar's button items, and implement the delegate pattern if necessary.
From iOS6 onwards, you can use container view. So what you have to do is take View controller, add the navigation bar to it, then add a Container View to same view controller. It will automatically, add the new view controller link to your container view. Now simply delete that, and your table view controller in the story board. Now embed the table view controller to container view by control drag. Hope it helps.
First add a navigation controller and put the table view controller (as root view controller) onto the navigation controller. This is how it is done in Code because I don't use IB.
Why in the world you can't drag a navigationItem into a .xib file with File's Owner set to a subclass of UIViewController and hook the navigationItem up to the UIViewController's navigationItem outlet is beyond me. It seems like a real hole in IB / XCode integration. Because you can certainly drag an instance of ViewController to a xib file, and drag a navigationItem into the ViewController, and then set the title and barbuttonitems that way.
So if you want to define your UITableViewController subclass object's navigation bar in IB, you have to create your TableVC object in a xib file (not the one .xib file that contains the tableview for your UITableViewController, though!). You then either hook the TableVC object up to be an outlet of another object (like your application delegate), which works if you need just one instance of your TVC throughout the lifetime of your app, or if you want to dynamically create instances of your TableVC in code you load this extra .xib file manually via loadNibNamed:owner:options method of the NSBundle class.
These steps worked for me in iOS 9:
Add a View Controller to the Storyboard. Make UITableViewController as base Class.
Add a Navigation Bar object onto view controller at the top.
Add a Table View below Navigation bar.
Add a Table View Cell into Table View.
Add constraints.
This is the other easy way ;
Choose your TableViewController screen on storyboard.
Click Size Inspector symbol on the right menu and find Simulated Size
Change Fixed to Free Form
You can add navigation bar easily.

Are there any Tab Bar events for notifying when someone hides/shows the Tab Bar?

I have a Nav controller inside a custom subclass of Tab Bar controller that i created.
I want to know from within the (custom) Tab Bar whenever one of the displayed controllers attempts to hide or show the Tab Bar. (for example when pushing a VC that has its hidesBottomBarWhenPushed=YES onto the Nac controller).
In short i want to be notified of events hiding/showing the Tab Bar but could not find anything in Apple's reference. I tried looking at UITabBar, UITabBarDelegate, UITabBarController, and UITabBarControllerDelegate but all seem to only provide functionality related to the tab bar items.
Thanks in advance.
If you are using a tab bar controller, UIKit explicitly states that every navigation controller instance that will be displayed in the tab bar controller's context will be among its viewControllers property. Now every UINavigationController instance has a delegate, which defines a navigationController:willShowViewController:animated: method which lets you know when a view controller is pushed onto it.
By setting your tab bar controller as the delegate of every navigation controller that is pushed onto it, you can analyze wether the view controller being pushed has the hidesBottomBarWhenPushed property set and generate an event when this is the case.
The algorithm used to hide the tab bar controller's tab bar is as follows: when a view controller is pushed on a navigation controller which is itself contained in a tab bar controller, if any view controller in the navigation stack of the navigation controller has the hidesBottomBarWhenPushed property set, then the tab bar should be hidden.
So the tab bar is hidden when a navigation controller is selected and one of the view controllers in its stack have the hidesBottomBarWhenPushed property set.
Subclass UINavigationController and implement the setter behind hidesBottomBarWhenPushed (or subclass the UIViewController to directly subclass the hidesBottomBarWhenPushed method) and delegate the call to the UITabBar (through a direct call or a NSNotification).

How do you set a the buttons in a UIToolbar for subview of Navigation Controller application using Interface Builder?

I have a navigation-based iPhone app that goes down 3 levels deep currently. The MainWindow nib has inside of the Navigation Controller a navigation bar, toolbar, and a reference to the Root View Controller which has the toolbar items and navigation items inside of it in the hierarchy of stuff in the nib file. My other view controllers are located in other nibs. How can I add items to the toolbar that appear in the toolbar when I drill down to other views using Interface Builder? I know it's possible to do it programmatically like this:
nextViewController.toolbarItems = arrayOfToolbarItems;
However, it seems like there should be a way to do this in Interface Builder. This shouldn't be a terribly uncommon task, so I'd like to improve my understanding of how to use IB for future reference.

Is there a good UITabBarController Example?

Is there a good UITabBarController example where it is NOT created in the appDelegate?
I would like to use a UITabBarController inside of a UIViewController, however dont know how to set the view outlet.
This is all very well documented here. It shouldn't matter where the UITabBarController instance is created, UIApplicationDelegate or not. In a nutshell, Create all of your respective UIViewController's and add them to an array. Then assign that array to your UITabBarController's viewControllers property. Then you can simply do something like [window addSubview:myTabBarController.view].
I'm just copy/pasting from the documentation here:
You should never access the tab bar
view of a tab bar controller directly.
To configure the tabs of a tab bar
controller, you assign the view
controllers that provide the root view
for each tab to the viewControllers
property. The order in which you
specify the view controllers
determines the order in which they
appear in the tab bar. When setting
this property, you should also assign
a value to the selectedViewController
property to indicate which view
controller is selected initially. (You
can also select view controllers by
array index using the selectedIndex
property.) When you embed the tab bar
controller’s view (obtained using the
inherited view property) in your
application window, the tab bar
controller automatically selects that
view controller and displays its
contents, resizing them as needed to
fit the tab bar interface.
Here's one implementation of UITabBarController initialized in a UIViewController.
The author also posted a github link to the xcode project.

How can I change the title of UINavigationBar Created in Interface builder

the issue is that I have created a UINavigationBar in interface builder and I want to change the title. The Navigation bar is not hooked up to my UINavigation controller. Is there any way I can accomplish this with the Navigation Bar as a stand alone from my Nib?
The second part of my question is more a general understanding of how the UINavigationBars work. I don't understand how the stack of navigation items works. for example what if i want to change the right button item to say "done" instead of "edit"? My understanding is that the left, center, and right bar button item are on a stack? but then how do I know which item is at what place in the stack. I'm sorry if I am missing something elementary here but I need some clarification on how the left, center and right bar button items are managed, and how the stack works into this. Thanks in advance.
You could use a custom titleView in the navigation bar, in which you have added a UILabel with the text of your choice.
Read the "Configuring the Navigation Item Object" section of Apple's View Controller Programming Guide for iPhone OS documentation for more information on how to customize the navigation bar.
create un IBOutlet of this UINavigationBar that you created in interface builder
#property (weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
then change title with
self.navigationBar.topItem.title = #"My Custom Title";
UINavigationController is a subclass of UIViewController, but unlike UIViewController it’s not usually meant for you to subclass. This is because navigation controller itself is rarely customized beyond the visuals of the nav bar.
An instance of UINavigationController can be created either in code or in an XIB file with relative ease. It’s thought of as a stack: it has a root view controller, and then new view controllers can be pushed onto the stack (often when the user taps on a row in a table) or popped off the stack (often by pressing the back button).
The root view controller can be set in an XIB by dragging the view controller under the navigation controller, or in code by using initWithRootViewController when you create it.
The Navigation Stack
Four methods are used to navigate user through the stack:
– pushViewController:animated:
– popViewControllerAnimated:
– popToRootViewControllerAnimated:
– popToViewController:animated: