Есть ли способ просмотреть UIViewController за другим UIViewController, не связываясь с окном AppDelegate?
Есть библиотека, которая мне действительно нравится, которую вы можете найти здесь ( https://github.com/pixyzehn/MediumMenu).
По сути это делает следующее:
Меню в задней части на самом деле является 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
всегда будет там.
Надеюсь это поможет!
Итак, ясно, что ваш сценарий таков:
rootViewController
= аUINavigationController
rootViewController
изUINavigationController
такое LoginController- Когда кто-то войдет в систему,
navigationController
толкать (или переходить) в меню контроллера
или же
rootViewController
такое LoginController- Когда кто-то залогинится успешно, он представит menuController
Таким образом, ключевой момент заключается в том, чтобы получить menuController, а не установить его в rootViewController
приложения.
Вот код, который я сделал некоторые изменения, чтобы соответствовать вашим требованиям. https://github.com/Moonsownner/MediumMenu-master
Что я сделал:
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() } }
- Я удаляю код в
MediumMenu
,
let menuController = UIViewController(); menuController.view = self UIApplication.sharedApplication(). делегат?.window??.rootViewController = contentController UIApplication.sharedApplication(). делегат?.window??.insertSubview(menuController.view, atIndex: 0)
и создайте новый контроллер с именем MediumMenuController
добавить MediumMenu
и другие контроллеры смотрят на это.
Может быть, это не ясно, сказав выше. Код может показать вам детали. Удачи.