Chris Chris - 4 months ago 17
iOS Question

Can't find where to add UIBarButtonItem

I have a UIPageViewController in a NavigationController and one of the ViewControllers presented by the UIPageViewController needs to be able to add a 'Save' button to the navigation bar.

The problem is that I can't find any access to the navigation bar, so I set a break point and began digging for it and I can't seem to find where there is any access to the NavigationController or it's properties.

This is what I found:

(lldb) po self.toolbarItems
$9 = 0x00000000 <nil>

(lldb) po self.parentViewController
$10 = 0x1e070bc0 <UIPageViewController: 0x1e070bc0>

(lldb) po self.parentViewController.toolbarItems
$11 = 0x00000000 <nil>

(lldb) po self.parentViewController.navigationController
$12 = 0x00000000 <nil>

(lldb) po self.parentViewController.view
$13 = 0x1d585960 <_UIPageViewControllerContentView: 0x1d585960; frame = (0 0; 320
416); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer:
0x1d5a1090>>

(lldb) po self.parentViewController.view.window
$14 = 0x1e073750 <UIWindow: 0x1e073750; frame = (0 0; 320 480); layer =
<UIWindowLayer: 0x1e0756a0>>

(lldb) po self.parentViewController.view.window.rootViewController
error: property 'rootViewController' not found on object of type 'id'
error: 1 errors parsing expression

(lldb) po self.presentingViewController
$15 = 0x00000000 <nil>


I've tried setting my rightBarButtonItem in my VC as well as the parent VC and even tried going to the topViewController and the rootViewController.

Can anyone offer any other suggestions as to where I might be able to get access to the NavigationController?

Answer

You need to put this in the UIViewController subclass

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.parentViewController.navigationItem.rightBarButtonItem = ...
}

The only problem with that solution is Apple can change the UIPageViewController implementation at anytime to have more levels of view controller containment. The safer solution is this:

In the UIViewController subclass .h add:

@property (nonatomic, weak) UIPageViewController *pageViewController;

in .m add:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _pageViewController.navigationItem.rightBarButtonItem = ...
}

and then don't forget to assign the pageViewController to the property in the appropriate location

myViewController.pageViewController = myPageViewController;

You could reset the UIPageViewController navigationItem's properties in the UIPageViewControllerDelegate Methods like this:

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
    if (completed) {
        UIViewController *viewController = [pageViewController.viewControllers lastObject];
        if (![viewController isKindOfClass:[CustomBarButtonItemViewController class]]) {
            pageViewController.navigationItem.rightBarButtonItem = nil;
        }
    }
}