XZ_iOS 动态添加viewController到tabBarController中

1、根据数据请求返回的数据,控制tabBar的item动态显示与隐藏:

HomeViewController.swift
private func getShowHiddenCeShi1() {
        
        let urlString = PostPath.isDisplayTest.path
        XZNetworkManager().requestWith(URLString: urlString, parameters: nil, headers: nil) {  (json, isSuccess)in
            
            if isSuccess {
                if 显示 {
                    if data["is_display"].stringValue == "2"{
                        // 显示 ‘测试’ 模块
                        XZConst.saveSingleKey("1",key: isOpenCeShi)
                    }else{
                        // 隐藏 ‘测试’ 模块
                        XZConst.saveSingleKey("0",key: isOpenCeShi)
                    }
                    
                    // 实时设置tabBarController
                    let mainTabBar =  UIApplication.shared.keyWindow?.rootViewController as? MainViewController
                    mainTabBar?.setUpChildViewControllerAgain()
                }
            }
        }
    } 

class MainViewController: UITabBarController {
        
    /// 重新设置子控制器
    func setUpChildViewControllerAgain2() {
        
        guard var childrenArr = self.viewControllers else { return }
        // guard var childrenArr = self.children else { return }
        // 获取本地存储的字段
        if  let isOpen:String = XZConst.getSingleKey(isOpenCeShi) {
            if isOpen == "1"{ // 显示 ‘测试’ 模块 - XZMyTestController
                let test = ["clsName":"XZMyTestController","title":"测试","imgName":"rongxin"]
                var hasTestModel = false
                childrenArr.forEach { (navigationVc) in
                    if let topNavigation = navigationVc as? NavigationController, let topViewController = topNavigation.topViewController {
                        if topViewController.isKind(of: XZMyTestController r.self) {
                            hasTestModel = true
                        }
                    }
                }
                
                if !hasTestModel {
                    let testCon = controller(dict: test)
                    childrenArr.insert(testCon, at: childrenArr.count-1)
                    self.viewControllers?.removeAll() // 非常重要
                    self.setViewControllers(childrenArr, animated: true)
                    print("--------------添加‘测试’成功!", self.children, "\n", self.viewControllers)
                }
            }else { // 不显示
                var hasTestModel = false
                childrenArr.forEach { (navigationVc) in
                    let rootVc = navigationVc.children
                    rootVc.forEach { (childVc) in
                        if childVc.isKind(of: XZMyTestController.self) {
                            hasTestModel = true
                        }
                    }
                }
                
                if hasTestModel {
                    childrenArr.enumerated().forEach({ (offset: Int, element: UIViewController) in
                        let rootVc = element.children
                        rootVc.forEach { (childVc) in
                            if childVc.isKind(of: XZMyTestController.self) {
                                childrenArr.remove(at: offset)
                                self.viewControllers?.removeAll() // 非常重要
                                self.setViewControllers(childrenArr, animated: true)
                                print("--------------删除‘测试’成功!", self.children, "\n", self)
                            }
                        }
                    })
                }
            }
        }
    }

    /// 使用字典创建一个子控制器
    ///
    /// - Parameter dict: [clsName,clsName,imgName]
    /// - Returns: 子控制器
    private func controller(dict:[String:String]) -> UIViewController {
        
        // 1.取得字典的值
        guard let clsName = dict["clsName"],
        let title = dict["title"],
        let imgName = dict["imgName"],
        let cls = NSClassFromString(Bundle.main.namespace + "." + clsName) as? UIViewController.Type
            else {
            return UIViewController()
        }
        
        var vc: UIViewController
        
        if dict["clsName"] == "XZMyIndexViewController" {
            let storyboard = UIStoryboard.init(name: "XZUserAccount", bundle: nil)
            vc = storyboard.instantiateViewController(withIdentifier: "XZMyIndexViewController") as! XZMyIndexViewController
            
        }else {
            // 2.创建视图控制器
            vc = cls.init()
        }
        
       
        
        // 3.给子控制器设置值
        vc.title = title
        
        let image = UIImage.init(named: "tabbar_" + imgName)
        vc.tabBarItem.image = image
        
        let imageSelected = UIImage.init(named:  "tabbar_" + imgName + "_selected")?.xz_originalRender
        
        vc.tabBarItem.selectedImage = imageSelected
        
        let nav = NavigationController.init(rootViewController: vc)
        
        // 4.设置 tabbar 的标题字体(大小)
        vc.tabBarItem.setTitleTextAttributes(
            [NSAttributedString.Key.foregroundColor: UIColor.appMainColor], for: .selected)
        // 系统默认是 12 号字,修改字体大小,要设置 Normal 的字体大小
        vc.tabBarItem.setTitleTextAttributes(
            [NSAttributedString.Key.font: Fonts_13.content],for: .normal)
        
        return nav
    }
    
}

需要注意的问题是:

1>给tabBarController重置子控制器的时候,需要调用的方法是setViewControllers

2>获取子控制器的方法使用viewControllers而不是children,如果tabBar的子控制器的数量大于5个,使用children获取出来的只是当前展示出来的5个,最后一个是UIMoreListController类型的,而使用viewControllers获取到的则是设置的子控制器。

3>setViewController调用之前,一定要先调用removeAll方法,去掉原来的控制器再重新设置,否则在获取新加的"测试"模块,以后该模块后面的模块的layer的位置会有问题。同理,设置timer、animation、viewControllers等等之前,也要先remove掉或销毁之前的,再设置新的;

2、如何获取UIMoreNavigationController和UIMoreListController的子控制器

之前使用children获取子控制器,获取到的子控制器是UIMoreNavigationController类型的,而该类型是苹果的私有属性,并没有公开出来,导致无法判断tabBar上是否存在"测试"模块的控制器。

下图是在MainViewController中获取viewControllers和children的打印图片:

XZ_iOS 动态添加viewController到tabBarController中_第1张图片

 

你可能感兴趣的:(iOS,Swift)