//1:动态获取命名空间 guard let name = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else { SHLog(message: "获取命名空间失败") return } let cls: AnyClass? = NSClassFromString(name + "." + VCName) //VCName:表示试图控制器的类名 // Swift中如果想通过一个Class来创建一个对象, 必须告诉系统这个Class的确切类型 guard let typeClass = cls as? UIViewController.Type else { SHLog(message: "cls不能当做UIViewController") return } let childController = typeClass.init()
根据上面的内容,下面看一个具体的例子
动态的显示UITabBar上的内容,包括图片、文字,所谓动态是指根据服务端返回的数据,动态显示底部UITabBar上的图片和文字,这里我们使用本地json文件进行模仿服务器返回的json数据,实现根据本地json文件加载显示对应的图片和内容,实现动态化设置,主体思路就是将子视图控制器的类名,显示的图片名称,title使用字典存储,使用数组存储所有相关字典,我们只需要拿到JSON文件并进行解析获得对应数据即可。注意一点,如果服务器没有返回JSON数据,那么使用默认数据。
首先看一下使用JSON文件和默认数据的显示效果图:
具体代码如下:
class MainViewController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() //ios7以后,只需要设置tintColor,那么图片和文字都会按照tintColor进行渲染 tabBar.tintColor = UIColor.orange //添加子控制器 addChildViewControllers() } }
在添加所有子控制器方法中,实现了读取本地JSON数据、将JSON数据转换为对象(数组字典)、遍历数组字典取出每一个字典
func addChildViewControllers() { //1:读取JSON数据 guard let filePath = Bundle.main.path(forResource: "MainVCSettings.json", ofType: nil) else { SHLog(message: "JSON文件不存在") return } guard let data = NSData(contentsOfFile: filePath) else { SHLog(message: "加载二进制数据失败") return } //2:将JSON数据转换为对象(数组字典) do { let dicts = try JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [[String: AnyObject]] //3:遍历数组字典取出每一个字典 for dict in dicts { let title = dict["title"] as? String let vcName = dict["vcName"] as? String let imageName = dict["imageName"] as? String addChildViewController(vcName: vcName, title: title, imageName: imageName) } } catch { // 只要try对应的方法发生了异常, 就会执行catch{}中的代码,即使用默认数据 addChildViewController(vcName: "HomeTableViewController", title: "首页", imageName: "tabbar_home") addChildViewController(vcName: "MessageTableViewController", title: "消息", imageName: "tabbar_message_center") addChildViewController(vcName: "DiscoverTableViewController", title: "发现", imageName: "tabbar_discover") addChildViewController(vcName: "ProfileTableViewController", title: "我", imageName: "tabbar_profile") } }
addChildViewController方法实现如下:
func addChildViewController(vcName: String?, title: String?, imageName: String?) { //1:动态获取命名空间,开发中应该充分利用guard语句,guard可以有效的解决可选绑定容易形成{}嵌套问题 guard let name = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else { SHLog(message: "获取命名空间失败") return } //2:根据字符串获取Class var cls: AnyClass? = nil if let controllerName = vcName{ cls = NSClassFromString(name + "." + controllerName) } //Swift中如果想通过一个Class来创建一个对象, 必须告诉系统这个Class的确切类型,这里注意:所有的视图控制器都是继承于UITableViewController guard let typeClass = cls as? UITableViewController.Type else { SHLog(message: "cls不能当做UITableViewController") return } //通过Class创建对象 let childController = typeClass.init() //3:设置控制器相关属性 childController.title = title if let imageName = imageName { //从内像外设置, nav和tabbar都有 childController.tabBarItem.image = UIImage(named: imageName) childController.tabBarItem.selectedImage = UIImage(named: "\(imageName)_highlighted") } //4:包装一个导航控制器 let nav = UINavigationController(rootViewController: childController) //5:添加子控制器到UITabBarController addChildViewController(nav) } JSON文件内容如下图:
参考:
命名空间 - Swift必备tips
命名空间