在 UISplitViewController 中,不能让 showDetailViewController:sender: push on detail navigationController

人气:601 发布:2022-10-16 标签: ios objective-c ios8 uisplitviewcontroller uinavigationcontroller

问题描述

在 iOS 8 中,视图控制器现在可以调用 showDetailViewController:sender: 让系统确定正确的视图控制器来呈现详细视图控制器.

In iOS 8, view controllers can now call showDetailViewController:sender: to have the system determine the proper view controller to present the detail view controller.

在我的应用程序中,我有一个 UISplitViewController,它的 viewControllers 数组中包含两个 UINavigationControllers.第一个 UINavigationController 包含我的主"视图,它是 UITableViewController 的子类.第二个 UINavigationController 包含我的详细"视图.

In my app, I have a UISplitViewController, which contains two UINavigationControllers in its viewControllers array. The first UINavigationController contains my 'master' view, a subclass of UITableViewController. The second UINavigationController contains my 'detail' view.

由于我试图使这项工作普遍适用,我正在尝试使用 showDetailViewController:sender: 来显示详细视图:

Since I'm trying to make this work universally, I'm trying to use showDetailViewController:sender: to display the detail view:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    self.itemVC.item = self.itemStore.items[indexPath.row];

    [self showDetailViewController:self.itemVC sender:self];
}

self.splitViewController.collapsed == YES 时,这适用于 Horizo​​ntal Compact trait(iPhone 风格),但当 trait 为 Regular(iPad,未折叠)时则不行.在 iPad 上,它用裸细节视图控制器替换了细节 UINavigationController(而不是替换那个 UINavigationController 的 viewControllers 数组).

This works fine with the Horizontal Compact trait (iPhone style), when self.splitViewController.collapsed == YES, but not when the trait is Regular (iPad, not collapsed). On the iPad, it replaces the detail UINavigationController with the bare detail view controller (instead of replacing that UINavigationController's viewControllers array).

为了解决这个问题,我测试了它是否已折叠,如果没有,我将在显示之前将详细视图控制器包装在另一个 UINavigationController 中:

To get around this, I'm tested for whether or not it's collapsed, and if it isn't, I'm wrapping the detail view controller in another UINavigationController before showing it:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    self.itemVC.item = self.itemStore.items[indexPath.row];

    UIViewController *vcToShow;

    // For whatever reason, when not collapsed, showDetailViewController replaces the detail view, doesn't push onto it.
    if (self.splitViewController.collapsed) {
        vcToShow = self.itemVC;
    } else {
        vcToShow = [[UINavigationController alloc] initWithRootViewController:self.itemVC];
    }

    [self showDetailViewController:vcToShow sender:self];
}

我想或者我可以只配置 self.itemVC 并避免在 self.splitViewController.collapsed == NO:

I suppose alternatively I could just configure self.itemVC and avoid calling showDetailViewController:sender: altogether when self.splitViewController.collapsed == NO:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    self.itemVC.item = self.itemStore.items[indexPath.row];

    // For whatever reason, when not collapsed, showDetailViewController replaces the detail view, doesn't push onto it.
    if (self.splitViewController.collapsed) {
        [self showDetailViewController:vcToShow sender:self];
    }
}

但是,这感觉违背了 showDetailViewController:sender: 的目的,即放松 self 与视图层次结构的其余部分之间的耦合.

But, this feels like it's defeating the purpose of showDetailViewController:sender:, which is to loosen up the coupling between self and the rest of the view hierarchy.

有没有更好的方法来处理这个问题?

Is there a better way to handle this?

推荐答案

showDetailViewController:sender: 取决于 collapse 属性你需要创建你想要的控制器显示在细节中.

In showDetailViewController:sender: depending on the collapse property you need to create the controller you want to show in the detail.

例如在 iPad 的横向模式下,它已经从情节提要中创建了详细视图控制器,但在 iPhone 5 上它被折叠时,视图控制器还不存在.

E.g. On the iPad in landscape mode it would already create the detail view controller from the storyboard but on the iPhone 5 where it is collapsed the view controller does not exist yet.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UINavigationController *detail;
    ImageViewController *imageVC;

   // on the iPhone (compact) the split view controller is collapsed
   // therefore we need to create the navigation controller and its image view controllerfirst
   if (self.splitViewController.collapsed) {
       detail = [[UINavigationController alloc] init];
       imageVC = [self.storyboard instantiateViewControllerWithIdentifier:@"ImageViewController"];
       [detail setViewControllers:@[imageVC] animated: NO];
   }
   // if the split view controller shows the detail view already there is no need to create the controllers
   else {
       id vc = self.splitViewController.viewControllers[1];
       if ([vc isKindOfClass:[UINavigationController class]]) {
           detail = (UINavigationController *)vc;
           imageVC = [detail.viewControllers firstObject];
       }
    }

    [self prepareImageViewController:imageVC forPhoto:self.photos[indexPath.row]];
    // ask the split view controller to show the detail view
    // the controller knows on iPhone and iPad how to show the detail
    [self.splitViewController showDetailViewController:detail sender:self];
}

希望这能解决您的问题.

I hope this solves your issue.

562