【问题标题】:UISplitView button missing after detail replace segue细节替换segue后UISplitView按钮丢失
【发布时间】:2014-01-06 16:14:27
【问题描述】:

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

如果我在纵向进行转场,则条形按钮将丢失,因为从未调用过 willHideViewController: 委托方法。当从主控调用prepareForSegue: 时,我正在将委托设置为新的细节控制器。

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

prepareForSegue:

UINavigationController *nav = [segue destinationViewController];
    UIViewController *destinationViewController = nav.topViewController;
    if ([destinationViewController conformsToProtocol:@protocol(UISplitViewControllerDelegate)]) {
        self.splitViewController.delegate = destinationViewController;
    }
    else {
        self.splitViewController.delegate = nil;
    }

在细节控制器中:

#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;
}

【问题讨论】:

  • 我刚遇到这个。从情节提要加载详细视图后,似乎没有重新调用上述方法(带有没有主按钮的新工具栏,并且没有重新调用这些委托方法。我没有解决方案这还没有,但如果你找到了,请分享/回答你自己的问题。

标签: ios objective-c ipad uisplitviewcontroller master-detail


【解决方案1】:

终于破解了,看了iOS8 Day by Day的课程,也就是splitViewController chapter 18.

发生在我身上的事情与此线程相似。最初,SpliViewController 使 DetailViewController 显示“展开”按钮。在segue之后,这将消失。 所以最初的想法是我的SplitViewController,onViewLoad(),接触到了DetailViewController。重新创建 DetailViewController 时,不会重现此自定义行为。 这是我的故事板,以便您可以更轻松地识别代码中的对象: 请注意主控制器和细节控制器都有导航控制器(我知道这是让它们与导航栏一起工作的方法,虽然我是 iOS 的爱好者,但我真的不知道)。

所以在逐块注释一些代码之后,在 TopStuffSpliViewController 我找到了导致这种行为的代码行:

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

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

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

小心,如果您忽略 if 语句,您还将隐藏单个细节控制器屏幕(如 iPhone 4S)上的后退按钮! 就是这样,它现在按预期工作!

【讨论】:

    【解决方案2】:

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

    步骤如下:

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

      所以,在 DetailViewControllers 中添加:

      @property (nonatomic, strong) UIBarButtonItem *rootPopoverButtonItem;
      

      在委托方法中:

      -(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;
      
      }
      
    2. 现在在您的 - (void)viewDidLoad 中读取存储的值并显示。如果 barButton 显示在被替换的 viewController 中,当前的 VC 将显示它。

        [self.navigationItem setLeftBarButtonItem:self.rootPopoverButtonItem animated:YES];
      
    3. 现在在主视图控制器中,在 prepareForSegue 中包含以下内容...

            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 协议,还有其他方法(更优雅)可用。但这看起来工作量太大,而且超出了能力范围。

    【讨论】:

    • 你碰巧有一个 Swift(短)版本的代码吗?基本上你正在做的是保存上下文并在实例更改时恢复它? (来自 Android 的程序员 POV)
    猜你喜欢
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 2017-12-01
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多