UISplitViewController - отклонение/всплытие Подробный просмотр контроллера в коде в спящем режиме

С iOS8 нам разрешено использовать UISplitViewController как на компактных, так и на обычных устройствах. Это здорово, потому что мне не нужно создавать две разные раскадровки для iPhone и iPad, но есть одна проблема, с которой я застрял.

Если контроллер с разделенным изображением находится на iPad (если обнуленное свойство равно NO), я могу просто вызвать это, чтобы показать MasterVC с левой стороны.

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;
[self.splitViewController.displayModeButtonItem action];

Но если это на iPhone (если скомпенсированное свойство равно YES), displayMode игнорируется и ничего не делает.

Я не могу поместить DetailVC в popToRootViewControllerAnimated, потому что у DetailVC есть собственный контроллер навигации.

Как Apple ожидает, что мы покажем MasterVC (отпустите DetailVC) в коде в спящем режиме, если нет никакого метода, например dismissViewControllerAnimated:completion: для контроллера представления, который был представлен с showDetail? Ваша помощь будет оценена по достоинству. Благодаря

Ответ 1

На устройствах, которые не поддерживают режим "split", если

  • Вы хотите представить контроллер главного представления вместо детали, когда сначала загружается UISplitViewController, а затем возвращает YES в свой класс делегата (UISplitViewControllerDelegate) Метод метода splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: должен сделать это:

    - (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
        return YES;
    }
    
  • Вы хотите отклонить контроллер подробного представления обратно к мастеру после определенного события (например, нажатие на кнопку). В этом случае вам нужно нажать контроллер навигации контроллера детали:

    [detailViewController.navigationController.navigationController popToRootViewControllerAnimated:YES]
    

Ответ 2

У нас возникла аналогичная проблема, пытающаяся вырваться из подробного представления в контроллере с разделенным представлением.

Хотя я уверен, что принятый ответ работает нормально, другой подход, который я нашел, что работает, а может быть немного чище, - это использовать разматывание.

Я настраиваю разворот на главном представлении, на котором я хотел вернуться, затем создал ссылку segue для разворачивания segue из представления, которое я хотел поп (обратите внимание: предполагает, что вы используете раскадровки).

Убедитесь, что вы установили IBAction в появившемся окне назначения, которое вы возвращаете:

-(IBAction)prepareForUnwind:(UIStoryboardSegue *)segue { }

Подключите выход к сегменту в раскадровке для разматывания. Извините, я не предоставляю много подробностей о том, как настроить раскрутку segue, но для этого доступно много учебников.

Затем на вашем контроллере, который вы хотите отклонить, подключите segue к разворачивающемуся сегменту контроллера, к которому вы возвращаетесь. Обязательно назовите segue.

Затем при нажатии кнопки на контроллере представления вы хотите убрать, просто позвоните

[self performSegueWithIdentifier:@"unwindSegueName" sender:self];

Это работало очень хорошо, и он не позволяет перекопать назад в иерархию навигации, которая может измениться.

Надеюсь, это полезно кому-то! Счастливые праздники!

Ответ 3

Спасибо pNre! Здесь код, который будет обрабатывать отображение пользовательской кнопки возврата при свертывании, и displayModeButton, когда он не рухнул.

lazy var backButtonItem: UIBarButtonItem = {
    UIBarButtonItem(image: UIImage(named: "backImage"), style: .plain, target: self, action: #selector(dismissAnimated))
}()

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    guard let svc = splitViewController else { return }

    if svc.isCollapsed {
        navigationItem.leftBarButtonItem = backButtonItem
    } else {
        navigationItem.leftBarButtonItem = svc.displayModeButtonItem
    }
}

func dismissAnimated() {
    _ = navigationController?.navigationController?.popViewController(animated: true)
}

Я поместил это в willLayoutSubviews() вместо viewDidLoad(), чтобы кнопка была обновлена ​​адаптивно, например, для изменений ориентации на iPhone 7 Plus и изменения размера класса, например, в режиме просмотра с разметкой на iPad.

Ответ 4

Вот что я в итоге сделал, чтобы открыть DetailVC, если мы находимся в свернутом состоянии (iPhone исключает +sizes), и показать/скрыть MasterVC, если мы не находимся в свернутом состоянии (iPad).

@IBAction func backTouchUp(_ sender: UIButton) {
    if let splitViewController = splitViewController,
        !splitViewController.isCollapsed {
        UIApplication.shared.sendAction(splitViewController.displayModeButtonItem.action!, to: splitViewController.displayModeButtonItem.target, from: nil, for: nil)
    } else {
        navigationController?.popViewController(animated: true)
    }
}