0

I have a Split VC as the entry point of my app. The detail VC is a UINavigationController, and I want to always hide the master VC so that I can only use it in popover from the toolbar.

My problem is that I don't have a way to put the barButtonItem from the master VC into my detail VC. The toolbar is always empty (I had to use self.toolbarHidden = NO; to force it to show because there is a navigation bar at the top).

I have the code below in the UINavigationController (the actual detail VC):

-(void) setBarButtonItem:(UIBarButtonItem *)barButtonItem {
  NSLog(@"adding toolbar button: %@", barButtonItem.title);

  UIToolbar *toolbar = [self toolbar];

  NSMutableArray *toolbarItems = [toolbar.items mutableCopy];

  if (_barButtonItem) [toolbarItems removeObject:_barButtonItem];

  if (barButtonItem) [toolbarItems insertObject:barButtonItem atIndex:0];

  _barButtonItem = barButtonItem;
}

Am I missing something? I also tried to insert it into the navigationbar instead of the toolbar, but it doesn't show up there either. Please ask for any info that I didn't provide in the comments.

electrichead
  • 1,124
  • 8
  • 20

1 Answers1

0

In case anyone else is trying to do the same thing, I am leaving an implementation to have a UINavigationController as the Detail VC in a splitViewController and have the button at the top of each view controller as you navigate through to show/hide the Master VC:

Your Detail VC has to implement the protocol below (so you need to @synthesize the barButtonItem):

@protocol SplitViewBarButtonItemPresenter <NSObject>
@property (nonatomic, strong) UIBarButtonItem *barButtonItem;
@end

You will need to grab and keep the barButtonItem passed from willHideViewController: in your Detail VC, but you have to do it in the Master VC. Use the following in your Master VC:

- (BOOL) splitViewController:(UISplitViewController *)sender
    shouldHideViewController:(UIViewController *)vc
               inOrientation:(UIInterfaceOrientation)orientation {

    return YES;
}

- (void)splitViewController:(UISplitViewController *)svc
     willHideViewController:(UIViewController *)aViewController
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
       forPopoverController:(UIPopoverController *)pc {

    barButtonItem.title = self.title;

    [self splitViewBarButtonItemPresenter].barButtonItem = barButtonItem;

}

- (void)splitViewController:(UISplitViewController *)svc
     willShowViewController:(UIViewController *)aViewController
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
       forPopoverController:(UIPopoverController *)pc {

    [self splitViewBarButtonItemPresenter].barButtonItem = nil;

}

- (id <SplitViewBarButtonItemPresenter>) splitViewBarButtonItemPresenter {

    id detailVC = [self.splitViewController.viewControllers lastObject];

    if ((![detailVC isKindOfClass:[MainDetailVC class]]) || (![detailVC conformsToProtocol:@protocol(SplitViewBarButtonItemPresenter)])) {

        detailVC = nil;
    }

    return detailVC;
}

In each of the view controllers that you want the button to show, use the following code (you can also put this in a class and inherit from it if they are all the same type):

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    UIBarButtonItem *newBtn = [[UIBarButtonItem alloc]
            initWithTitle:@"Show Master MC" // might want a better title
            style:UIBarButtonItemStylePlain
            target:self action:@selector(forceOpenMasterVC)];

    self.navigationItem.rightBarButtonItem = newBtn;

}

-(void)forceOpenMasterVC {
    [((MainDetailVC *) self.navigationController) forceOpenMasterVC];
}

Then in your Detail VC, use the following:

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// Above line is needed because of self.barButtonItem.action
// It doesn't leak as far as I can tell

-(void)forceOpenMasterVC {
    // Grab the Master VC
    UIViewController * vc = [[self.splitViewController viewControllers] objectAtIndex:0];

    if (self.barButtonItem) {
        [self.barButtonItem.target
            performSelector:self.barButtonItem.action
            withObject: self.barButtonItem];
    }
}

If anyone has a better way, please include it.

electrichead
  • 1,124
  • 8
  • 20