代码创建子控制器
AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UITabBar.appearance().tintColor = UIColor.orange
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = ZFTabBarController()
window?.makeKeyAndVisible()
return true
}
}
ZFTabBarController.swift
第一种方式,直接重载一个addChildViewController方法,扩充一些想传的属性
import UIKit
class ZFTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
addChildViewController(childController: UITableViewController(), tabItemTitle: "首页", tabItemImage: "tabbar_home", tabBarSelectedImage: "tabbar_home_highlighted")
addChildViewController(childController: UITableViewController(), tabItemTitle: "消息", tabItemImage: "tabbar_discover", tabBarSelectedImage: "tabbar_discover_highlighted")
addChildViewController(childController: UITableViewController(), tabItemTitle: "发现", tabItemImage: "tabbar_compose_icon_add", tabBarSelectedImage: "tabbar_compose_icon_add_highlighted")
addChildViewController(childController: UITableViewController(), tabItemTitle: "我", tabItemImage: "tabbar_profile", tabBarSelectedImage: "tabbar_profile_highlighted")
}
func addChildViewController(childController: UIViewController,tabItemTitle:String,tabItemImage:String,tabBarSelectedImage:String) {
self.addChildViewController(childController)
childController.title = tabItemTitle
childController.tabBarItem.image = UIImage(named: tabItemImage)
childController.tabBarItem.selectedImage = UIImage(named: tabBarSelectedImage)
}
}
第二种方式,通过类名字符串创建控制器
import UIKit
class ZFTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
addChildViewController(childControllerClass: "ZFHomeViewController", tabItemTitle: "首页", tabItemImage: "tabbar_home", tabBarSelectedImage: "tabbar_home_highlighted")
addChildViewController(childControllerClass: "ZFMsgViewController", tabItemTitle: "消息", tabItemImage: "tabbar_discover", tabBarSelectedImage: "tabbar_discover_highlighted")
addChildViewController(childControllerClass: "ZFDiscoverViewController", tabItemTitle: "发现", tabItemImage: "tabbar_compose_icon_add", tabBarSelectedImage: "tabbar_compose_icon_add_highlighted")
addChildViewController(childControllerClass: "ZFProfileViewController", tabItemTitle: "我", tabItemImage: "tabbar_profile", tabBarSelectedImage: "tabbar_profile_highlighted")
}
func addChildViewController(childControllerClass: String,tabItemTitle:String,tabItemImage:String,tabBarSelectedImage:String) {
//swift要保证每一个对象的值都要严格的类型匹配,所以一定要使用可选类型先尝试创建,然后判断对象是否为nil后再做后面的工作
//自定义的类要先获取命名空间,而不能直接使用类名的字符串
//CFBundleExecutable字段在哪里看?info.plist -> Executable file
guard let namespace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String else
{
print("命名空间获取失败")
return
}
//确保命名空间获取到以后,将命名空间和类名字符串通过 命名空间 + "." + 类名字符串 的格式拼接
guard let childClassStr = NSClassFromString(namespace + "." + childControllerClass) else {
print("找不到Class\(childControllerClass)")
return
}
//确保前面获取到的完整类标识属于UIViewController类型
guard let childVCType = childClassStr as? UIViewController.Type else {
print("没有获取到对应的控制器类型")
return
}
//经过如上的过滤,确保这个类字符串真的是一个UIViewController的类型,才能做对控制器的一些属性设置等常规操作
let childVC = childVCType.init()
childVC.title = tabItemTitle
childVC.tabBarItem.image = UIImage(named: tabItemImage)
childVC.tabBarItem.selectedImage = UIImage(named: tabBarSelectedImage)
self.addChildViewController(childVC)
}
}
第三种,读取一个json文件来通过字符串创建子控制器
假如json如下:
[
{
"vcName": "ZFHomeViewController",
"title": "首页",
"imageName": "tabbar_home"
},
{
"vcName": "ZFMsgViewController",
"title": "消息",
"imageName": "tabbar_message_center"
},
{
"vcName": "ZFDiscoverViewController",
"title": "发现",
"imageName": "tabbar_discover"
},
{
"vcName": "ZFProfileViewController",
"title": "我",
"imageName": "tabbar_profile"
}
]
import UIKit
class ZFTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
//先读取json
guard let jsonPath = Bundle.main.path(forResource: "MainVCSettings.json", ofType: nil) else {
print("json文件不存在")
return
}
//如果json文件读取成功,再看看能不能转换成二进制数据
guard let jsonData = NSData.init(contentsOfFile: jsonPath) else {
print("数据错误")
return
}
//如果二进制数据转换成功,尝试解析json
guard let tempObject = try? JSONSerialization.jsonObject(with: jsonData as Data, options: .mutableContainers) else {
return
}
//json解析成功,再来尝试能不能把json转换成字典数组,[[String : Any]]表示字典数组
guard let dictArray = tempObject as? [[String : Any]] else {
return
}
//以上过滤都通过,就可以放心的使用稳定的json转换为的字典数组中的数据了
for dict in dictArray
{
guard let vcName = dict["vcName"] as? String else {
continue
}
guard let title = dict["title"] as? String else {
continue
}
guard let imageName = dict["imageName"] as? String else {
continue
}
//按照方式二创建各个子控制器
addChildViewController(childControllerClass: vcName, tabItemTitle: title, tabItemImage: imageName, tabBarSelectedImage: imageName + "_highlighted")
}
}
func addChildViewController(childControllerClass: String,tabItemTitle:String,tabItemImage:String,tabBarSelectedImage:String) {
//info.plist -> Executable file
guard let namespace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String else
{
print("命名空间获取失败")
return
}
guard let childClassStr = NSClassFromString(namespace + "." + childControllerClass) else {
print("找不到Class\(childControllerClass)")
return
}
guard let childVCType = childClassStr as? UIViewController.Type else {
print("没有获取到对应的控制器类型")
return
}
let childVC = childVCType.init()
childVC.title = tabItemTitle
childVC.tabBarItem.image = UIImage(named: tabItemImage)
childVC.tabBarItem.selectedImage = UIImage(named: tabBarSelectedImage)
self.addChildViewController(childVC)
}
}