关于ios:UISplitView按钮在细节替换segue后丢失

UISplitView button missing after detail replace segue

我有一个主要的iPad详细信息界面,该界面设置了情节提要,以提供详细视图控制器上的替换设置。这可以很好地替换细节控制器,但是在某些情况下,缺少用于显示主控制器的条形按钮。

如果我在纵向模式下执行segue,则会丢失bar按钮,因为从未调用willHideViewController:委托方法。当从主机调用prepareForSegue:时,我将委托设置为新的详细信息控制器。

当缺少按钮时,我可以将iPad旋转到横向,然后再回到纵向,然后按钮就会出现。

prepareForSegue:

1
2
3
4
5
6
7
8
UINavigationController *nav = [segue destinationViewController];
    UIViewController *destinationViewController = nav.topViewController;
    if ([destinationViewController conformsToProtocol:@protocol(UISplitViewControllerDelegate)]) {
        self.splitViewController.delegate = destinationViewController;
    }
    else {
        self.splitViewController.delegate = nil;
    }

在详细信息控制器中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma mark - Split view

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
    barButtonItem.title = NSLocalizedString(@"MasterButton", @"Master");
    [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
    self.masterPopoverController = popoverController;
}

- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
    // Called when the view is shown again in the split view, invalidating the button and    popover controller.
    [self.navigationItem setLeftBarButtonItem:nil animated:YES];
    self.masterPopoverController = nil;
}


看完iOS8日复一日课程,即splitViewController第18章,我终于破解了它。

对我来说,发生的事情与此线程相似。最初,SpliViewController使DetailViewController显示\\'Expand \\'按钮。发生争执之后,这将消失。
因此,最初的想法是我的SplitViewController onViewLoad()接触了DetailViewController。重新创建DetailViewController时,不会重现此自定义行为。
这是我的情节提要,以便您可以更轻松地识别代码中的对象:
enter

因此,在逐块注释一些代码之后,在TopStuffSpliViewController中,我找到了导致此行为的代码行:

1
2
let detailNavVC = self.childViewControllers.last as! UINavigationController
    detailNavVC.topViewController!.navigationItem.leftBarButtonItem = self.displayModeButtonItem()

现在只需要在DetailController每次加载时重新创建此行为即可:

1
2
3
4
5
override func viewDidLoad() {
        super.viewDidLoad()
....
if (self.navigationController?.splitViewController?.collapsed == false {
    self.navigationItem.leftBarButtonItem = self.navigationController?.splitViewController?.displayModeButtonItem()}

请注意,如果忽略if语句,您还将在iPhone 4S之类的单个详细信息控制器屏幕上隐藏后退按钮!
就是这样,它现在可以按预期工作了!


我遇到了同样的情况,并且解决了是否将barButton值从当前的detailViewController(将被替换)传递到prepareForSegue方法中的目标detailViewController(即替换的那个)中的问题。

步骤为:

  • 将barButton作为属性存储在UISplitViewDelegate方法中

    因此,在DetailViewControllers中添加:

    1
    @property (nonatomic, strong) UIBarButtonItem *rootPopoverButtonItem;

    在委托方法中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    -(void)splitViewController:(UISplitViewController *)svc willHideViewController:
    (UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem
     forPopoverController:(UIPopoverController *)pc
    {
         barButtonItem.title = @"Master";
         [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
         self.rootPopoverButtonItem = barButtonItem; //Storing the barButton
         self.masterPopoverController = pc;

    }

    -(void)splitViewController:(UISplitViewController *)svc willShowViewController:
    (UIViewController *)aViewController
    invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {

       // Called when the view is shown again in the split view, invalidating the button and popover controller.

        [self.navigationItem setLeftBarButtonItem:nil animated:YES];
        self.rootPopoverButtonItem = nil;  //Storing the barButton
        self.masterPopoverController = nil;

    }
  • 现在,在-(void)viewDidLoad中读取存储的值并显示。如果barButton在被替换的viewController中显示,则当前的VC将显示它。

    1
      [self.navigationItem setLeftBarButtonItem:self.rootPopoverButtonItem animated:YES];
  • 现在在主视图控制器中的prepareForSegue ...中包括以下内容...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
          UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController;
          UINavigationController *currentNavigationController = [splitViewController.viewControllers lastObject];
          UINavigationController *navigationController = [segue destinationViewController];

          DetailViewController *destinationDetailViewController=(DetailViewController *)[navigationController topViewController];
          DetailViewController *currentDetailViewController =(DetailViewController *)[currentNavigationController topViewController];

          splitViewController.delegate = destinationDetailViewController;//Needed for passing the delegate

          if(currentDetailViewController.rootPopoverButtonItem !=nil)
          {

          destinationDetailViewController.rootPopoverButtonItem = currentDetailViewController.rootPopoverButtonItem;

          }

  • 这不是一种优雅的方法。但是为我工作却没有太多开销。如果可以使用SubstitutableDetailViewController协议,则还有其他方法(更优雅)可用。但这看起来工作量太大,而且超出了功能。