【问题标题】:I have an error to add a root view handler in AppDelegate我在 AppDelegate 中添加根视图处理程序时出错
【发布时间】:2017-05-18 18:48:28
【问题描述】:

我正在开发一个启动屏幕类似于 Twitter 的应用程序,我想用 MMDrawer 实现一个抽屉式导航,但我有一个错误提示 "UIViewControllerHierarchyInconsistency ',原因:'添加一个根视图控制器作为视图控制器的子级:'"

我附上了 AppDelegate 代码 我希望你能帮助我,非常感谢你阅读我!问候。

//
//  AppDelegate.swift
//  Rodrigo
//
//  Created by expo on 02/03/17.
//  Copyright © 2017 Rodrigo. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?
    var drawerContainer:MMDrawerController?



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        //Personaliza la vista
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window! .backgroundColor = UIColor(red: 35/255, green: 34/255, blue: 34/255, alpha:1)
        self.window!.makeKeyAndVisible()

        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

        //Recuerda al usuario
        let userId = UserDefaults.standard.string(forKey: "userId")
        if (userId != nil )
        {

            buildNavigationDrawer()


        }
            //Fin de recordar al usuario

        else{


            //rootViewController from storyboard

            let navigationController = mainStoryboard.instantiateViewController(withIdentifier: "navigationController")
            self.window!.rootViewController = navigationController


            //logomask
            navigationController.view.layer.mask = CALayer()
            navigationController.view.layer.mask?.contents = UIImage(named: "logoGrande500pts")!.cgImage
            navigationController.view.layer.mask?.bounds = CGRect(x:0, y:0, width: 60, height: 60)
            navigationController.view.layer.mask?.anchorPoint = CGPoint (x: 0.5, y: 0.5)
            navigationController.view.layer.mask?.position = CGPoint (x: navigationController.view.frame.width / 2, y: navigationController.view.frame.height / 2)

            //logo mask background view
            let maskBigView = UIView(frame: navigationController.view.frame)
            maskBigView.backgroundColor = UIColor.white
            navigationController.view.addSubview(maskBigView)
            navigationController.view.bringSubview(toFront: maskBigView)

            //logo mask animation
            let transformAnimation = CAKeyframeAnimation (keyPath: "bounds")
            transformAnimation.duration = 0.5
            transformAnimation.beginTime = CACurrentMediaTime() + 1

            let initalBounds = NSValue(cgRect: (navigationController.view.layer.mask?.bounds)!)
            let secondBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 50, height: 50))
            let finalBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 2000, height: 2000))

            transformAnimation.values = [initalBounds, secondBounds, finalBounds]
            transformAnimation.keyTimes = [0, 0.5, 1]
            transformAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
            transformAnimation.isRemovedOnCompletion = false
            transformAnimation.fillMode = kCAFillModeForwards
            navigationController.view.layer.mask?.add(transformAnimation, forKey: "maskAnimation")

            UIView.animate(withDuration: 0.1, delay: 1.35, options: UIViewAnimationOptions.curveEaseIn,
                           animations: {
                            maskBigView.alpha = 0.0
            },
                           completion: {finished in
                            maskBigView.removeFromSuperview()
            })



            UIView.animate(withDuration: 0.25,
                           delay: 1.3,
                           options: UIViewAnimationOptions(),
                           animations: {
                            self.window!.rootViewController!.view.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)


            },
                           completion: {finished in
                            UIView.animate(withDuration: 0.3,
                                           delay: 0.0,
                                           options : UIViewAnimationOptions.curveEaseInOut,
                                           animations: {
                                            self.window!.rootViewController!.view.transform = CGAffineTransform.identity
                            },
                                           completion: nil
                            )
            })

        }


        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

    func CAAnimationDelegate (anim: CAAnimation!, finished flag: Bool){
        self.window!.rootViewController!.view.layer.mask=nil
    }



    func buildNavigationDrawer(){

        //Personaliza la vista
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window! .backgroundColor = UIColor(red: 35/255, green: 34/255, blue: 34/255, alpha:1)
        self.window!.makeKeyAndVisible()



        let mainStoryBoard:UIStoryboard = UIStoryboard(name:"Main", bundle:nil)
        let navigationController:PrincipalViewController = mainStoryBoard.instantiateViewController(withIdentifier: "PrincipalViewController") as! PrincipalViewController
        let leftSideMenu:LeftSideViewController = mainStoryBoard.instantiateViewController(withIdentifier: "LeftSideViewController") as! LeftSideViewController
        let rightSideMenu:RightSideViewController = mainStoryBoard.instantiateViewController(withIdentifier: "RightSideViewController") as! RightSideViewController


        let mainPageNav = UINavigationController(rootViewController: navigationController)


     window?.rootViewController = drawerContainer
     self.window?.rootViewController = mainPageNav


        let leftSideMenuNav = UINavigationController(rootViewController:leftSideMenu)
        let rightSideMenuNav = UINavigationController(rootViewController:rightSideMenu)


        drawerContainer = MMDrawerController(center: mainPageNav, leftDrawerViewController: leftSideMenuNav, rightDrawerViewController: rightSideMenuNav)

        drawerContainer!.openDrawerGestureModeMask = MMOpenDrawerGestureMode.panningCenterView
        drawerContainer!.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.panningCenterView



        /*
         let navigationController = mainStoryboard.instantiateViewController(withIdentifier: "PrincipalViewController") as! PrincipalViewController
         let mainPageNav = UINavigationController(rootViewController: navigationController)
         self.window?.rootViewController = mainPageNav
        */

        //logomask
        navigationController.view.layer.mask = CALayer()
        navigationController.view.layer.mask?.contents = UIImage(named: "logoGrande500pts")!.cgImage
        navigationController.view.layer.mask?.bounds = CGRect(x:0, y:0, width: 60, height: 60)
        navigationController.view.layer.mask?.anchorPoint = CGPoint (x: 0.5, y: 0.5)
        navigationController.view.layer.mask?.position = CGPoint (x: navigationController.view.frame.width / 2, y: navigationController.view.frame.height / 2)
        //logo mask background view
        let maskBigView = UIView(frame: navigationController.view.frame)
        maskBigView.backgroundColor = UIColor.white
        navigationController.view.addSubview(maskBigView)
        navigationController.view.bringSubview(toFront: maskBigView)
        //logo mask animation
        let transformAnimation = CAKeyframeAnimation (keyPath: "bounds")
        transformAnimation.duration = 0.5
        transformAnimation.beginTime = CACurrentMediaTime() + 1
        let initalBounds = NSValue(cgRect: (navigationController.view.layer.mask?.bounds)!)
        let secondBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 50, height: 50))
        let finalBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 2000, height: 2000))
        transformAnimation.values = [initalBounds, secondBounds, finalBounds]
        transformAnimation.keyTimes = [0, 0.5, 1]
        transformAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
        transformAnimation.isRemovedOnCompletion = false
        transformAnimation.fillMode = kCAFillModeForwards
        navigationController.view.layer.mask?.add(transformAnimation, forKey: "maskAnimation")
        UIView.animate(withDuration: 0.1, delay: 1.35, options: UIViewAnimationOptions.curveEaseIn,
                       animations: {
                        maskBigView.alpha = 0.0
        },
                       completion: {finished in
                        maskBigView.removeFromSuperview()
        })
        UIView.animate(withDuration: 0.25,
                       delay: 1.3,
                       options: UIViewAnimationOptions(),
                       animations: {
                        self.window!.rootViewController!.view.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
        },
                       completion: {finished in
                        UIView.animate(withDuration: 0.3,
                                       delay: 0.0,
                                       options : UIViewAnimationOptions.curveEaseInOut,
                                       animations: {
                                        self.window!.rootViewController!.view.transform = CGAffineTransform.identity
                        },
                                       completion: nil
                        )
        })


    }


}

【问题讨论】:

    标签: ios swift appdelegate mmdrawercontroller


    【解决方案1】:

    你得到的错误很清楚。

    问题出在这里:

    window?.rootViewController = drawerContainer
    self.window?.rootViewController = mainPageNav
    

    您正在设置rootViewController,然后在下一行,用不同的东西再次设置它。

    然后,几行之后,你这样做:

    drawerContainer = MMDrawerController(center: mainPageNav, leftDrawerViewController: leftSideMenuNav, rightDrawerViewController: rightSideMenuNav)
    

    您正在获取窗口的 rootViewController,并尝试将其作为子级添加到另一个容器视图控制器。

    明显的修复:

    1. 删除这一行:

      self.window?.rootViewController = mainPageNav
      
    2. 更改rootViewController 赋值和drawerContainer 实例化的顺序。现在,你正在扔掉原来的 drawerContainer 是什么(如果它有任何价值的话)。

      drawerContainer = MMDrawerController(center: mainPageNav, leftDrawerViewController: leftSideMenuNav, rightDrawerViewController: rightSideMenuNav)
      

      需要提前来

      window?.rootViewController = drawerContainer
      

    您的代码可能还有更多问题,但这两个肯定是问题。

    【讨论】:

    • 嗨 Dima,感谢您的回复,我尝试按照您的建议进行操作,我删除了 Self.window 这一行? .rootViewController = mainPageNav 而这行 Window? .rootViewController =drawerContainer 我把它放在我的函数“func buildNavigationDrawer()”的键之后并且在运行应用程序时出现此错误“致命错误:在展开可选值(Lldb)时意外发现nil”
    • 我在你的截图中没有看到window?.rootViewController = drawerContainer
    • window?.rootViewController = drawerContainer 需要在您实际创建它之后。你把它们倒过来了。
    【解决方案2】:

    我将我的代码附在解决方案中

    //
    //  AppDelegate.swift
    //  Expodiseño
    //
    //  Created by expo on 02/03/17.
    //  Copyright © 2017 Creategia360. All rights reserved.
    //
    
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
        var drawerContainer:MMDrawerController?
    
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
            //Personaliza la vista
            self.window = UIWindow(frame: UIScreen.main.bounds)
            self.window! .backgroundColor = UIColor(red: 35/255, green: 34/255, blue: 34/255, alpha:1)
            self.window!.makeKeyAndVisible()
    
            let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
            //Recuerda al usuario
            let userId = UserDefaults.standard.string(forKey: "userId")
            if (userId != nil )
            {
    
                //let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let navigationController = mainStoryboard.instantiateViewController(withIdentifier: "PrincipalViewController") as! PrincipalViewController
                let mainPageNav = UINavigationController(rootViewController: navigationController)
                self.window?.rootViewController = mainPageNav
    
                //logomask
                navigationController.view.layer.mask = CALayer()
                navigationController.view.layer.mask?.contents = UIImage(named: "logoGrande500pts")!.cgImage
                navigationController.view.layer.mask?.bounds = CGRect(x:0, y:0, width: 60, height: 60)
                navigationController.view.layer.mask?.anchorPoint = CGPoint (x: 0.5, y: 0.5)
                navigationController.view.layer.mask?.position = CGPoint (x: navigationController.view.frame.width / 2, y: navigationController.view.frame.height / 2)
    
                //logo mask background view
                let maskBigView = UIView(frame: navigationController.view.frame)
                maskBigView.backgroundColor = UIColor.white
                navigationController.view.addSubview(maskBigView)
                navigationController.view.bringSubview(toFront: maskBigView)
    
                //logo mask animation
                let transformAnimation = CAKeyframeAnimation (keyPath: "bounds")
                transformAnimation.duration = 0.5
                transformAnimation.beginTime = CACurrentMediaTime() + 1
    
                let initalBounds = NSValue(cgRect: (navigationController.view.layer.mask?.bounds)!)
                let secondBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 50, height: 50))
                let finalBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 2000, height: 2000))
    
                transformAnimation.values = [initalBounds, secondBounds, finalBounds]
                transformAnimation.keyTimes = [0, 0.5, 1]
                transformAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
                transformAnimation.isRemovedOnCompletion = false
                transformAnimation.fillMode = kCAFillModeForwards
                navigationController.view.layer.mask?.add(transformAnimation, forKey: "maskAnimation")
    
                UIView.animate(withDuration: 0.1, delay: 1.35, options: UIViewAnimationOptions.curveEaseIn,
                               animations: {
                                maskBigView.alpha = 0.0
                },
                               completion: {finished in
                                maskBigView.removeFromSuperview()
                })
    
    
    
                UIView.animate(withDuration: 0.25,
                               delay: 1.3,
                               options: UIViewAnimationOptions(),
                               animations: {
                                self.window!.rootViewController!.view.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
    
    
                },
                               completion: {finished in
                                UIView.animate(withDuration: 0.3,
                                               delay: 0.0,
                                               options : UIViewAnimationOptions.curveEaseInOut,
                                               animations: {
                                                self.window!.rootViewController!.view.transform = CGAffineTransform.identity
                                },
                                               completion: nil
                                )
                })
    
           buildNavigationDrawer()
    
            }
                //Fin de recordar al usuario
    
            else{
    
    
    
                //rootViewController from storyboard
    
                let navigationController = mainStoryboard.instantiateViewController(withIdentifier: "navigationController")
                self.window!.rootViewController = navigationController
    
    
                //logomask
                navigationController.view.layer.mask = CALayer()
                navigationController.view.layer.mask?.contents = UIImage(named: "logoGrande500pts")!.cgImage
                navigationController.view.layer.mask?.bounds = CGRect(x:0, y:0, width: 60, height: 60)
                navigationController.view.layer.mask?.anchorPoint = CGPoint (x: 0.5, y: 0.5)
                navigationController.view.layer.mask?.position = CGPoint (x: navigationController.view.frame.width / 2, y: navigationController.view.frame.height / 2)
    
                //logo mask background view
                let maskBigView = UIView(frame: navigationController.view.frame)
                maskBigView.backgroundColor = UIColor.white
                navigationController.view.addSubview(maskBigView)
                navigationController.view.bringSubview(toFront: maskBigView)
    
                //logo mask animation
                let transformAnimation = CAKeyframeAnimation (keyPath: "bounds")
                transformAnimation.duration = 0.5
                transformAnimation.beginTime = CACurrentMediaTime() + 1
    
                let initalBounds = NSValue(cgRect: (navigationController.view.layer.mask?.bounds)!)
                let secondBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 50, height: 50))
                let finalBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 2000, height: 2000))
    
                transformAnimation.values = [initalBounds, secondBounds, finalBounds]
                transformAnimation.keyTimes = [0, 0.5, 1]
                transformAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
                transformAnimation.isRemovedOnCompletion = false
                transformAnimation.fillMode = kCAFillModeForwards
                navigationController.view.layer.mask?.add(transformAnimation, forKey: "maskAnimation")
    
                UIView.animate(withDuration: 0.1, delay: 1.35, options: UIViewAnimationOptions.curveEaseIn,
                               animations: {
                                maskBigView.alpha = 0.0
                },
                               completion: {finished in
                                maskBigView.removeFromSuperview()
                })
    
    
    
                UIView.animate(withDuration: 0.25,
                               delay: 1.3,
                               options: UIViewAnimationOptions(),
                               animations: {
                                self.window!.rootViewController!.view.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
    
    
                },
                               completion: {finished in
                                UIView.animate(withDuration: 0.3,
                                               delay: 0.0,
                                               options : UIViewAnimationOptions.curveEaseInOut,
                                               animations: {
                                                self.window!.rootViewController!.view.transform = CGAffineTransform.identity
                                },
                                               completion: nil
                                )
                })
    
            }
    
    
            // Override point for customization after application launch.
            return true
        }
    
        func applicationWillResignActive(_ application: UIApplication) {
            // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
            // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        }
    
        func applicationDidEnterBackground(_ application: UIApplication) {
            // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
            // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        }
    
        func applicationWillEnterForeground(_ application: UIApplication) {
            // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        }
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        }
    
        func applicationWillTerminate(_ application: UIApplication) {
            // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        }
    
        func CAAnimationDelegate (anim: CAAnimation!, finished flag: Bool){
            self.window!.rootViewController!.view.layer.mask=nil
        }
    
        func buildNavigationDrawer(){
    
            let mainStoryBoard:UIStoryboard = UIStoryboard(name:"Main", bundle:nil)
            let navigationController:PrincipalViewController = mainStoryBoard.instantiateViewController(withIdentifier: "PrincipalViewController") as! PrincipalViewController
            let leftSideMenu:LeftSideViewController = mainStoryBoard.instantiateViewController(withIdentifier: "LeftSideViewController") as! LeftSideViewController
            let rightSideMenu:RightSideViewController = mainStoryBoard.instantiateViewController(withIdentifier: "RightSideViewController") as! RightSideViewController
    
    
            let mainPageNav = UINavigationController(rootViewController: navigationController)
            let leftSideMenuNav = UINavigationController(rootViewController:leftSideMenu)
            let rightSideMenuNav = UINavigationController(rootViewController:rightSideMenu)
    
    
            //  self.window!.rootViewController = navigationController
            drawerContainer = MMDrawerController(center: mainPageNav, leftDrawerViewController: leftSideMenuNav, rightDrawerViewController: rightSideMenuNav)
    
            drawerContainer!.openDrawerGestureModeMask = MMOpenDrawerGestureMode.panningCenterView
            drawerContainer!.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.panningCenterView
    
            window?.rootViewController = drawerContainer
            //self.window?.rootViewController = mainPageNav
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      相关资源
      最近更新 更多