web-dev-qa-db-ja.com

UISplitViewControllerで、showDetailViewController:senderを作成できません:詳細navigationControllerにプッシュします

IOS 8では、ViewControllerがshowDetailViewController:sender:を呼び出して、詳細ViewControllerを表示するための適切なViewControllerをシステムに決定させることができるようになりました。

私のアプリには、viewControllers配列に2つのUINavigationControllersを含むUISplitViewControllerがあります。最初のUINavigationControllerには、UITableViewControllerのサブクラスである「マスター」ビューが含まれています。 2番目のUINavigationControllerには、「詳細」ビューが含まれています。

私はこれを普遍的に機能させようとしているので、showDetailViewController:sender:を使用して詳細ビューを表示しようとしています。

- (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トレイト(iPhoneスタイル)では正常に機能しますが、トレイトが通常(iPad、折りたたまれていない)の場合は機能しません。 iPadでは、詳細UINavigationControllerを(そのUINavigationControllerのviewControllers配列を置き換える代わりに)ベア詳細ビューコントローラーに置き換えます。

これを回避するために、折りたたまれているかどうかをテストします。折りたたまれていない場合は、詳細ビューコントローラーを別のUINavigationControllerでラップしてから、次のように表示します。

- (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を設定して、showDetailViewController:sender:のときに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];
    }
}

しかし、これは、selfとビュー階層の残りの部分との間の結合を緩めるというshowDetailViewController:sender:の目的を無効にしているように感じます。

これを処理するためのより良い方法はありますか?

18
Jeff V

showDetailViewController:sender:collapseプロパティに応じて、詳細に表示するコントローラーを作成する必要があります。

例えば。横向きモードのiPadでは、ストーリーボードから詳細ビューコントローラーが既に作成されていますが、折りたたまれているiPhone 5では、ビューコントローラーはまだ存在しません。

- (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];
}

これで問題が解決することを願っています。

7
Peter Oettl

あなたがそれをする方法には問題があります。選択後にデバイスを回転させる(モードを折りたたみからallVisibleに変更する)と、ナビゲーションコントローラーのない詳細vcが表示されます。

すべての場合にshowDetailViewController:sender:を呼び出し、ナビゲーションコントローラーを使用してView Controllerを渡すと、どちらの場合も正常に機能し、上記の回転の問題も修正されます。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.itemVC.item = self.itemStore.items[indexPath.row];

    UIViewController *vcToShow= [[UINavigationController alloc] initWithRootViewController:self.itemVC];
    [self showDetailViewController:vcToShow sender:self];
}
0
Ismail