美文网首页
Swift使用runtime全局变量获取控制器

Swift使用runtime全局变量获取控制器

作者: 玉思盈蝶 | 来源:发表于2020-06-20 07:05 被阅读0次

runtime是不是在OC中用的比较多?runtime我确实接触的少,之前也就是在OC中交换两个方法中用到,这段时间在我们项目里看到这方面代码了,然后也遇到了一些问题,学习了,这里也记录下吧~~~

代码如下:

extension AppDelegate {
    @discardableResult
    func getKeyWindow() -> UIWindow {
        guard let window = self.window else {
            let window = UIWindow(frame: UIScreen.main.bounds)
            window.backgroundColor = UIColor.white
            window.makeKeyAndVisible()
            self.window = window
            return window
        }
        if !window.isKeyWindow {
            window.makeKeyAndVisible()
        }
        return window
    }
}

private var homeKey: Void?
private var navKey: Void?
private var waiterKey: Void?
private var personKey: Void?

extension UIApplication {
// 首页控制器
    fileprivate(set) var homeViewController: HomeViewController? {
        get {
            return objc_getAssociatedObject(self, &homeKey) as? HomeViewController
        }
        set {
            objc_setAssociatedObject(self, &homeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 导航控制器
    var navigationController: BaseNavigationController? {
        get {
            return objc_getAssociatedObject(self, &navKey) as? BaseNavigationController
        }
        set {
            objc_setAssociatedObject(self, &navKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        
    }
    
    // 某一个控制器
    var waiterHomeViewController:WaiterHomeViewController?{
        get {
            return objc_getAssociatedObject(self, &waiterKey) as? WaiterHomeViewController
        }
        set {
            objc_setAssociatedObject(self, &waiterKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 某一个控制器
    var personalCenterViewController:PersonalCenterViewController?{
        get {
            return objc_getAssociatedObject(self, &personKey) as? PersonalCenterViewController
        }
        set {
            objc_setAssociatedObject(self, &personKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    
    // 获取首页控制器
    private func getHomeViewController() -> HomeViewController {
        if let home = UIApplication.shared.homeViewController {
            return home
        }
        let home = HomeViewController()
        UIApplication.shared.homeViewController = home
        return home
    }
    
    // 获取window
    private func getKeyWindow() -> UIWindow {
        return (UIApplication.shared.delegate as! AppDelegate).getKeyWindow()
    }
    
    // 获取导航控制器
    private func getNavigationController() -> BaseNavigationController {
        if let nav = UIApplication.shared.navigationController {
            getKeyWindow().rootViewController = nav
            return nav
        }
        let nav = BaseNavigationController()
        UIApplication.shared.navigationController = nav
        getKeyWindow().rootViewController = nav
        return nav
    }
    
    private func getWaiterHomeViewController() -> WaiterHomeViewController {
        if let waiter = waiterHomeViewController {
            return waiter
        }
        let vc = UIStoryboard(name: "WaiterHome", bundle: Bundle.main).instantiateInitialViewController() as! WaiterHomeViewController
        waiterHomeViewController = vc
        return vc
    }
    
    
    private func getPersonalCenterViewController() -> PersonalCenterViewController {
        if let personal = personalCenterViewController {
            return personal
        }
        
        let vc = PersonalCenterViewController()
        personalCenterViewController = vc
        return vc
    }
    
    // 跳转到首页控制器
    func gotoHomeViewController(with animated: Bool = true) {
        
        func toHome(with nav: BaseNavigationController) {
            var childs = nav.children
            for vc in childs.reversed() {
                vc.resignFirstResponder()
                vc.presentedViewController?.dismiss(animated: false, completion: nil)
            }
            
            if let home = childs.first, home.isMember(of: HomeViewController.self) {
                nav.popToRootViewController(animated: animated)
            }else {
                childs.removeAll()
                let home = getHomeViewController()
                childs.append(home)
                nav.setViewControllers(childs, animated: animated)
            }
        }
        
        let nav = getNavigationController()
        toHome(with: nav)
    }
    
    func gotoPersonalCenterViewController(with animated: Bool = true) {
        
        let nav = getNavigationController()
        
        if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
            let childs = nav.children
            for vc in childs.reversed() {
                vc.resignFirstResponder()
                vc.presentedViewController?.dismiss(animated: false, completion: nil)
            }
            return
        }
        
        let vc = getPersonalCenterViewController()
        if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
            nav.pushViewController(vc, animated: animated)
        }else {
            gotoHomeViewController(with: false)
            let nav = getNavigationController()
            nav.pushViewController(vc, animated: animated)
        }
    }
    
    func gotoWaiterHomeViewController(with animated: Bool = true) {
        
        let nav = getNavigationController()
        
        if let top = nav.topViewController, top.isMember(of: WaiterHomeViewController.self) {
            let childs = nav.children
            for vc in childs.reversed() {
                vc.resignFirstResponder()
                vc.presentedViewController?.dismiss(animated: false, completion: nil)
            }
            return
        }
        
        let vc = getWaiterHomeViewController()
        if let top = nav.topViewController, top.isMember(of: PersonalCenterViewController.self) {
            if !top.isKind(of: WaiterHomeViewController.self) {
                nav.pushViewController(vc, animated: animated)
            }
        }else {
            gotoPersonalCenterViewController(with: false)
            let nav = getNavigationController()
            if let top = nav.topViewController, !top.isKind(of: WaiterHomeViewController.self)  {
                nav.pushViewController(vc, animated: animated)
            }
        }
    }
    
    func pop2Business() {
        
        gotoWaiterHomeViewController(with: false)
        
        let nav = getNavigationController()
        let temp = BusinessViewController()
        temp.canGoBack = false
        let business = BaseNavigationController(rootViewController: temp)
        nav.topViewController?.popup(controller: business, direction: .center, enableDismiss: true)
    }
    
    func gotoRootViewController() {
        let root = RootViewController()
        getKeyWindow().rootViewController = root
    }
}

代码大概的意思代码里有注释。

我们项目里的这些需要频繁跳转的控制器就是在这里统一跳转,以前写这个代码的说是当时是为了低设备性能考虑,不频繁的创建控制器,所以创建了一个全局的控制器。

遇到的问题:

1、启动程序,不走设置UIApplication.shared.navigationController的代码时,存在代码中取UIApplication.shared.navigationController的时候不能push,因为此时UIApplication.shared.navigationController是nil。

暂时我是这么取可以的:

extension UIApplication {
    
    var baseNavigationController: BaseNavigationController? {
        if let nav = (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController as? BaseNavigationController {
            return nav
        } else {
            for window in UIApplication.shared.windows.reversed() {
                if let nav = window.rootViewController as? BaseNavigationController {
                    return nav
                }
            }
        }
        
        return nil
    }
}

2、创建这些runtime设置的全局控制器变量后需要设置一下UIApplication里的控制器,需要更新,不然会一直引用,会出现内存泄露。

暂时就遇到这些问题吧,记录一下~~大家周末快乐!!!

PS:话说你们项目里的各种跳转控制器和取导航控制器都是怎么处理的,我现在有点迷茫了。。。。。。呜呜~~

相关文章

网友评论

      本文标题:Swift使用runtime全局变量获取控制器

      本文链接:https://www.haomeiwen.com/subject/isxwxktx.html