Есть ли способ просмотреть UIViewController за другим UIViewController, не связываясь с окном AppDelegate?

Есть библиотека, которая мне действительно нравится, которую вы можете найти здесь ( https://github.com/pixyzehn/MediumMenu).

По сути это делает следующее:

MediumMenu Demo

Меню в задней части на самом деле является UIViewController. Если мы углубимся в исходный код, мы найдем следующий очень важный код:

public init(items: [MediumMenuItem], forViewController: UIViewController) {
    self.init()
    self.items = items
    height = screenHeight - 80 // auto-calculate initial height based on screen size
    frame = CGRect(x: 0, y: 0, width: screenWidth, height: height)
    contentController = forViewController
    menuContentTableView = UITableView(frame: frame)
    menuContentTableView?.delegate = self
    menuContentTableView?.dataSource = self
    menuContentTableView?.showsVerticalScrollIndicator = false
    menuContentTableView?.separatorColor = UIColor.clearColor()
    menuContentTableView?.backgroundColor = menuBackgroundColor
    addSubview(menuContentTableView!)

    if panGestureEnable {
        let pan = UIPanGestureRecognizer(target: self, action: #selector(MediumMenu.didPan(_:)))
        contentController?.view.addGestureRecognizer(pan)
    }

    let menuController = UIViewController()
    menuController.view = self

   UIApplication.sharedApplication().delegate?.window??.rootViewController = contentController
   UIApplication.sharedApplication().delegate?.window??.insertSubview(menuController.view, atIndex: 0)
}

Первые несколько строк не очень важны, но самые последние строки (те, которые касаются UIApplication.sharedApplication().delegate?.window?? являются ключом к работе этой библиотеки, но они также ограничивают библиотеку.

В соответствии с этими строками мы создаем UIViewController, для которого мы хотим, чтобы меню было rootViewController а затем мы добавляем вид меню в окно с индексом 0 (я предполагаю, что это то, что ставит его позади, позади contentController).

Проблема с библиотекой:

Библиотека работает, только если вы хотите меню на начальном контроллере представления. В некотором смысле, только если contentController уже является rootViewController. Это на самом деле будет работать для меня в моем приложении, но я не могу вернуться к своему исходному UIViewController, потому что он больше не находится в иерархии.

У меня есть сценарий, в котором у меня есть контроллер вида входа в систему, и когда вы успешно войдете в систему, я перейду к вашему контроллеру UINavigationController, в котором я хочу меню. Первым явным признаком проблемы является то, что я получаю жалобу "Предупреждение. Попытка представить UINavigationController на LoginViewController, чье представление не находится в иерархии окон!" Очевидно, что это не в иерархии окон, потому что я переназначаю rootViewController.

Я не знаю, как это исправить. Есть ли способ заставить эту функциональность работать, когда UIViewController, на котором я хочу, чтобы меню не было начальным контроллером представления?

3 ответа

Краткий ответ: да.

Это может быть реализовано с помощью назначения UIViewControllerTransitioningDelegate к ViewController содержащий list-menu и реализации interactionControllerForPresentation() а также interactionControllerForDismissal() методы. Вам не нужно трогать UIWindow (напрямую).

Вы можете просто изменить эту часть о существующих library но, судя по всему, это просто TableView с причудливым переходом. Вы можете легко реализовать это самостоятельно.

Обратитесь к справочнику Apple по API по интерактивным переходам и этому руководству Рэя Вендерлиха, чтобы получить практический пример.

Вы можете достичь этого, выполнив следующие действия.

(я делаю LoginViewController как твой rootViewController,

(ii) После успешного входа в систему перенаправьте пользователя на главный экран. Это ваш первый экран, который вы хотите показать после успешного входа в систему.

(iii) Вы можете сделать родительский класс UIViewControllers где вы хотите показать меню.

(iv) После этого, когда вы инициализируете UIViewControllerродительский класс позвонит public init(items: [MediumMenuItem], forViewController: UIViewController) метод и в том, что вы можете заменить две последние строки с кодом ниже.self.view.insertSubview(menuController.view, atIndex: 0)

(v) Нажав кнопку выхода, вы можете просто закрыть представленный контроллер представления, поэтому LoginViewController всегда будет там.

Надеюсь это поможет!

Итак, ясно, что ваш сценарий таков:

  1. rootViewController = а UINavigationController
  2. rootViewController из UINavigationController такое LoginController
  3. Когда кто-то войдет в систему, navigationController толкать (или переходить) в меню контроллера

или же

  1. rootViewController такое LoginController
  2. Когда кто-то залогинится успешно, он представит menuController

Таким образом, ключевой момент заключается в том, чтобы получить menuController, а не установить его в rootViewController приложения.

Вот код, который я сделал некоторые изменения, чтобы соответствовать вашим требованиям. https://github.com/Moonsownner/MediumMenu-master

Что я сделал:

  1. MediumMenu на самом деле это UIView, мы должны создать контроллер, чтобы содержать его, чтобы сделать переход. Так что я делаю новый класс с именем MediumMenuController, И вы можете видеть, я двигаю функцию showMenu в MediumMenuController, Так что если кто-то хочет показать меню вручную, целью должен быть MediumMenuController, а не предыдущий NavigationController, И MediumMenuController будет содержать ваш бизнес-контроллер, который вы отправите в функцию инициализации MediumMenuController,
class MediumMenuController: UIViewController {

    let menuView: MediumMenu
    let child: UIViewController

    init(items: [MediumMenuItem], childController: UIViewController){
        self.menuView = MediumMenu(items: items, forViewController: childController)
        self.child = childController
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(menuView)
        addChildViewController(child)
        self.view.addSubview(child.view)
        child.view.frame = UIScreen.mainScreen().bounds
        child.didMoveToParentViewController(self)

    }

    func showMenu() {
        menuView.show()
    }

}
  1. Я удаляю код в MediumMenu,

let menuController = UIViewController(); menuController.view = self UIApplication.sharedApplication(). делегат?.window??.rootViewController = contentController UIApplication.sharedApplication(). делегат?.window??.insertSubview(menuController.view, atIndex: 0)

и создайте новый контроллер с именем MediumMenuController добавить MediumMenu и другие контроллеры смотрят на это.

Может быть, это не ясно, сказав выше. Код может показать вам детали. Удачи.

Другие вопросы по тегам