В UISplitViewController невозможно сделать showDetailViewController: отправитель: нажать на детальную навигациюController

В iOS 8 контроллеры представлений теперь могут вызывать showDetailViewController:sender:, чтобы система определяла правильный контроллер представления, чтобы представить контроллер подробного представления.

В моем приложении у меня есть UISplitViewController, который содержит два UINavigationControllers в своем массиве viewControllers. Первый UINavigationController содержит мой "главный" вид, подкласс UITableViewController. Второй UINavigationController содержит мое представление "detail".

Поскольку я пытаюсь сделать эту работу универсально, я пытаюсь использовать showDetailViewController:sender: для отображения подробного представления:

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

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

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

Это отлично работает с характеристикой Horizontal Compact (стиль iPhone), когда self.splitViewController.collapsed == YES, но не тогда, когда черта является регулярной (iPad не рушится). На iPad он заменяет деталь UINavigationController нечетным контроллером подробных представлений (вместо замены этого массива viewControllers UINavigationController).

Чтобы обойти это, я тестировался на то, рушился он или нет, и если это не так, я завершу контроллер подробного представления в другой 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];
    }
}

Но это похоже на то, что он побеждает цель showDetailViewController:sender:, которая должна ослабить связь между self и остальной иерархией представлений.

Есть ли лучший способ справиться с этим?

Ответы

Ответ 1

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

Надеюсь, это решит вашу проблему.

Ответ 2

То, как вы это делаете, имеет проблему. Если вы выберете устройство (измените режим с момента его сглаживания на allVisible) после выбора, вы найдете деталь vc без контроллера навигации.

Если вы вызываете showDetailViewController:sender: во всех случаях и передаете контроллер вида с помощью навигационного контроллера, он будет работать нормально в обоих случаях, а также устранит проблему ротации, упомянутую выше.

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

Ответ 3

if (self.splitViewController.collapsed)
    [self.splitViewController showDetailViewController:self.itemVC sender:self];
else
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;