【问题标题】:Is there a way to view a UIViewController behind another UIViewController without messing with the AppDelegate window?有没有办法在不弄乱 AppDelegate 窗口的情况下查看另一个 UIViewController 后面的 UIViewController?
【发布时间】:2017-01-25 10:07:39
【问题描述】:

这里有一个我非常喜欢的图书馆 (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。问题的第一个明显迹象是我收到投诉 “警告:尝试在其视图不在窗口层次结构中的 LoginViewController 上呈现 UINavigationController!” 显然,它不在窗口层次结构中,因为我正在重新分配 rootViewController。

我不知道如何解决这个问题。当我想要菜单的 UIViewController 不是初始视图控制器时,有没有办法让这个功能起作用?

【问题讨论】:

  • 你的初始UIViewControllerUINavigationController吗?

标签: ios uiviewcontroller appdelegate uiwindow rootviewcontroller


【解决方案1】:

简短的回答是:是的

这可以通过将UIViewControllerTransitioningDelegate 分配给包含list-menuViewController 并实现interactionControllerForPresentation()interactionControllerForDismissal() 方法来实现。您不必触摸UIWindow直接)。

您可以只更改现有library 的这一部分,但从外观上看,它只是一个带有花哨过渡的TableView。您可以自己轻松实现。

查看 Apple 关于交互式过渡的 API Reference 和 Ray Wenderlich 的 this tutorial 以获取示例。

【讨论】:

    【解决方案2】:

    您可以通过以下步骤来实现它。

    (i) 将LoginViewController 设为您的rootViewController

    (ii) 当用户成功登录时,将用户重定向到主屏幕。这是您成功登录后要显示的第一个屏幕。

    (iii) 您可以在要显示菜单的地方创建UIViewControllers 的父类。

    (iv) 之后,当你初始化任何UIViewController 时,父类将调用public init(items: [MediumMenuItem], forViewController: UIViewController) 方法,你可以用下面的代码替换最后两行。 self.view.insertSubview(menuController.view, atIndex: 0)

    (v) 在点击退出按钮时,您可以简单地关闭呈现的视图控制器,因此LoginViewController 将始终存在。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      所以很明显你的场景是:

      1. rootViewController = 一个UINavigationController
      2. UINavigationControllerrootViewController 是 LoginController
      3. 当有人登录成功时,navigationController 推送(或转接)到 menuController

      1. rootViewController 是登录控制器
      2. 当有人登录成功时,会出现menuController

      所以关键是要获取一个menuController,而不是设置为app的rootViewController

      这是我为满足您的要求而进行了一些更改的代码。 https://github.com/Moonsownner/MediumMenu-master

      我做了什么:

      1. MediumMenu 实际上是一个UIView,我们必须创建一个控制器来包含它以便进行转换。所以我创建了一个名为MediumMenuController 的新类。你可以看到我将函数showMenu 移动到MediumMenuController。所以如果有人想手动显示菜单,目标必须是 MediumMenuController 而不是之前的NavigationControllerMediumMenuController 将包含您的业务控制器,您将其发送到 MediumMenuController 的 init 函数中。
      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中的代码。

      让 menuController = UIViewController(); menuController.view = 自我 UIApplication.sharedApplication().delegate?.window??.rootViewController = contentController UIApplication.sharedApplication().delegate?.window??.insertSubview(menuController.view, atIndex: 0)

      并创建一个名为 MediumMenuController 的新控制器,以将 MediumMenu 和其他控制器视图添加到其中。

      上面说的可能不清楚。该代码可以向您显示详细信息。祝你好运。

      【讨论】:

      • 你的答案应该显示关键代码的添加,而不是单独的删除,因为最终 yhat 链接会中断,这个答案将毫无意义
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-04
      • 2019-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-14
      相关资源
      最近更新 更多