通过服务器返回的数据来创建子控制器
来源:互联网 发布:mac屏保 windows 编辑:程序博客网 时间:2024/06/16 05:57
如果你有看过这个项目之前的代码,肯定知道我在搭建首页模块的时候,是通过离线数组来创建子控制器的:
/// 创建子控制器private func setupChildViewControllers() { // FIXME: - 从网络获取标题的Tabs,然后通过JSON来设置标题 // 创建子控制器的标题 let titles = ["分类", "推荐", "精品", "直播", "广播"] // 创建标题样式 let titleStyle = TitleStyle() titleStyle.titleViewHeight = 44 titleStyle.isScrollEnable = false // 设置标题下面的指示器是否可以滚动(其实默认为不可以滚动) titleStyle.selectedTextColor = UIColor(r: 246, g: 91, b: 90) // 设置选中标题的颜色 titleStyle.scrollSlideBackgroundColor = UIColor(r: 246, g: 91, b: 90) // 设置滚动指示器的背景颜色 titleStyle.isShowScrollSlide = true // 需要滚动指示器 titleStyle.isNeedScale = false // 需要对选中标题进行缩放 titleStyle.titleFont = UIFont.systemFont(ofSize: 15) // 设置子控制器标题文字大小 titleStyle.titleBackgroundColor = UIColor(r: 246, g: 246, b: 246) // 设置子控制器标题的背景颜色 // 创建一个数组,用来存放子控制器 var childVcs = [UIViewController]() // 创建子控制器并将其添加到childVcs数组中 childVcs.append(CategoryViewController()) // 分类子控制器 childVcs.append(RecommendViewController()) // 推荐子控制器 childVcs.append(BoutiqueViewController()) // 精品子控制器 childVcs.append(LiveViewController()) // 直播子控制器 childVcs.append(BroadcastViewController()) // 广播子控制器 // 创建containerView的frame // - 注意:设置containerView的高度时,一定不要忘记减去 // - 状态栏、导航栏和tabBar的高度,否则,后面在相应控制 // - 器的view中添加内容时,会导致有一部分内容被tabBar给 // - 遮挡的情况出现 let containerFrame = CGRect(x: 0, y: kStatusBarHeight + kNavigationBarHeight, width: kScreenWidth, height: kScreenHeight - kStatusBarHeight - kNavigationBarHeight - kTabBarHeight - kTabBarMargin) // 调用自定义构造函数,根据实际需求创建合适的ContainerView对象 let containerView = ContainerView(frame: containerFrame, titles: titles, titleStyle: titleStyle, childVcs: childVcs, parentVc: self) // 将创建好的ContainerView对象添加到当前控制器的View中 view.addSubview(containerView)}
也就是说,我们事先在本地确定好子控制器的标题和数量,然后再创建子控制器。这是最常规的做法,而且也可能是性能最好的做法。但是,如果是相对于一个重度依赖网络数据,并且有可能需要对标题、子控制器数量,以及子控制器选中状态进行动态修改的应用来说,这种做法其实并不灵活。好的做法是,通过服务器返回的数据来确定标题及其数量,这样我们就可以灵活的修改数据,而不用重新上架应用了。
接下来,我们所要做的就是,发送网络数据,然后对服务器返回的数据进行解析,最后再将解析完成的标题存放到数组中,之后再通过这个数组来创建子控制器及其标题。首先我们来看一下如何发送网络数据:
/// RequestURLprivate let kRequestURL = "http://recpage.c.qingting.fm/v3/navbar"class NavBarViewModel: NSObject { /// 用于存储转换完成的模型数据 lazy var navBarModelArray = [NavBarModel]()}extension NavBarViewModel { /// 请求网络数据并将其转换为模型 func requestData(completionHandler: @escaping () -> ()) { // 通过Alamofrie来发送网络请求 NetworkTools.shareTools.requestData(kRequestURL, .get, parameters: ["wt": "json", "v": "6.0.4", "deviceid": "093e8b7e24c02246fe92373727e4a92c", "phonetype": "iOS", "osv": "11.1.1", "device": "iPhone", "pkg": "com.Qting.QTTour"]) { (result) in /// 将JSON数据转成字典 guard let resultDict = result as? [String: Any] else { return } /// 根据字典中的关键字data取出字典中的数组数据 guard let resultArray = resultDict["data"] as? [[String: Any]] else { return } /// 遍历数组resultArray,取出它里面的字典 for dict in resultArray { // 将字典转为模型 let item = NavBarModel(dict: dict) // 将转换完成的模型存储起来 self.navBarModelArray.append(item) } // 数据回调 completionHandler() } }}
在将网络数据转成模型的过程中,我们没有借助任何的第三方框架,是直接通过KVC来完成的。在设计模型文件的时候,需要对服务器返回的JSON数据进行分析:
上面返回的这个JSON数据比较简单,基本上没有什么嵌套,并且唯一的一个嵌套字典link没什么用,我们可以不用解析。另外,需要特别强调的是,在Swift 4中利用KVC进行字典转模型的时候,一定不要忘记在类的定义前面加上属性关键字@objcMembers,否则键值匹配会失效:
@objcMembersclass NavBarModel: NSObject { // MARK: - 服务器返回的模型属性 /// 标题 var title: String = "" /// urlScheme var urlScheme: String = "" /// 当前子控制器是否被选中 var current: Bool = false // MARK: - 自定义构造函数 /// 将字典转为模型 init(dict: [String: Any]) { super.init() // 利用KVC将字典转为模型 setValuesForKeys(dict) } override func setValue(_ value: Any?, forUndefinedKey key: String) { }}
网络数据请求和字典转模型的工作都做完了之后,再回到控制器中,修改创建子控制器的代码。当然,前面一定要声明一个viewModel属性,用来请求数据。有了数据之后,就可以从模型性取出标题了,然后就可以通过网络数据来创建子控制器及其标题了:
/// 创建子控制器private func setupChildViewControllers() { // 发送网络请求,获取网络上的标题 navBarViewModel.requestData { // 从模型中取出标题,并且将其存放到一个数组中 let titles = self.navBarViewModel.navBarModelArray.map({ $0.title }) // 创建标题样式 let titleStyle = TitleStyle() titleStyle.titleViewHeight = 44 titleStyle.isScrollEnable = false // 设置标题下面的指示器是否可以滚动(其实默认为不可以滚动) titleStyle.selectedTextColor = UIColor(r: 246, g: 91, b: 90) // 设置选中标题的颜色 titleStyle.scrollSlideBackgroundColor = UIColor(r: 246, g: 91, b: 90) // 设置滚动指示器的背景颜色 titleStyle.isShowScrollSlide = true // 需要滚动指示器 titleStyle.isNeedScale = false // 需要对选中标题进行缩放 titleStyle.titleFont = UIFont.systemFont(ofSize: 15) // 设置子控制器标题文字大小 titleStyle.titleBackgroundColor = UIColor(r: 246, g: 246, b: 246) // 设置子控制器标题的背景颜色 // 创建一个数组,用来存放子控制器 var childVcs = [UIViewController]() // 创建子控制器并将其添加到childVcs数组中 childVcs.append(CategoryViewController()) // 分类子控制器 childVcs.append(RecommendViewController()) // 推荐子控制器 childVcs.append(BoutiqueViewController()) // 精品子控制器 childVcs.append(LiveViewController()) // 直播子控制器 childVcs.append(BroadcastViewController()) // 广播子控制器 // 创建containerView的frame // - 注意:设置containerView的高度时,一定不要忘记减去 // - 状态栏、导航栏和tabBar的高度,否则,后面在相应控制 // - 器的view中添加内容时,会导致有一部分内容被tabBar给 // - 遮挡的情况出现 let containerFrame = CGRect(x: 0, y: kStatusBarHeight + kNavigationBarHeight, width: kScreenWidth, height: kScreenHeight - kStatusBarHeight - kNavigationBarHeight - kTabBarHeight - kTabBarMargin) // 调用自定义构造函数,根据实际需求创建合适的ContainerView对象 let containerView = ContainerView(frame: containerFrame, titles: titles, titleStyle: titleStyle, childVcs: childVcs, parentVc: self) // 将创建好的ContainerView对象添加到当前控制器的View中 self.view.addSubview(containerView) }}
原本只是一行代码的事情,而我们却多搞了两个文件,一个NavBarViewModel文件,以及一个NavBarModel文件,并且还多写了好多代码,这么做绝对不是为了装逼,而是有着非常明确的现实需求——不必通过重新提交应用到App Store就可以动态的修改子控制器的标题及其数量。当然,这个也不是随便就能修改的,前提是项目中有与之对应的类。项目代码参见QTRadio。
- 通过服务器返回的数据来创建子控制器
- 通过服务器返回来JSON歌词数据进行解析
- 通过libcurl向服务器发送数据,返回的数据说明
- HBASE通过预先创建regions,来平衡数据的负载
- 通过storyboard创建控制器
- 通过storyboard创建控制器
- NavagationController的子控制器取消右滑返回的方法
- 怎么通过http向服务器发送数据并接受到返回的数据
- .net通过url访问服务器获取服务器返回数据
- 通过工具来监控webService请求和返回时的数据
- 通过工具来监控webService请求和返回时的数据
- 通过添加数据环境(Data Environment)来创建用于数据绑定的数据源。
- 服务器返回的json数据,通过本地解析调用SBjson的类
- CS端通过IIS去获得服务器数据的返回地址性错误解决方法
- Photon 分布式服务器架设-创建数据传入子服务器(二)
- 通过Hyperic-hq产品的基础包sigar.jar来实现服务器状态数据的获取
- 通过Hyperic-hq产品的基础包sigar.jar来实现服务器状态数据的获取
- 以自己的电脑作为服务器,Android端通过JSON来传递数据到后台
- Tomcat 实战篇
- 欢迎使用CSDN-markdown编辑器
- c++primer 第一章课后习题 编程代码
- PHP 二维数组求平均值
- “自顶向下, 逐步求精”的程序设计方法。
- 通过服务器返回的数据来创建子控制器
- 中文垃圾邮件检测
- 流形学习方法概述
- C语言的注释
- 第三章
- 工资管理C++
- 【ML算法】回归拟合——线性回归
- BZOJ3172 [Tjoi2013]单词 【AC自动机】
- Spring Boot的web开发(1)