##第三天
今天我们主要做访客视图的处理
1.因为每个界面都有一个tableView,我们就给BaseViewController添加一个tableView
1.1 添加并设置tableView
/// 表格视图 - 如果没有登录,就不创建 var tableView:UITableView?
// 设置表格视图 func setupTableView() { tableView = UITableView(frame: view.bounds, style: .plain) view.insertSubview(tableView!, belowSubview: navigationBar) // 设置数据源和代理 tableView?.delegate = self tableView?.dataSource = self // 设置内容缩进 tableView?.contentInset = UIEdgeInsets(top: navigationBar.bounds.height, left: 0, bottom: tabBarController?.tabBar.bounds.height ?? 49, right: 0) }
1.2 通过一个extension遵守tableView的协议,实现代理方法
// MARK: - tableView delegate extension XQWBBaseViewController: UITableViewDelegate, UITableViewDataSource { // 基类准备方法,子类具体实现 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return UITableViewCell() }}// 这里return 0 和 return UITableViewCell() 只是为了语法正确,具体的返回还需要子类重写实现``` 1.3 给tableView绑定假数据,添加上拉/下拉控件 - 创建 refreshControl
/// 刷新控件var refreshControl: UIRefreshControl?/// 区分上拉刷新标记var isPullup = false
- 设置 refreshControl
// 设置刷新控件 refreshControl = UIRefreshControl() tableView?.addSubview(refreshControl!) refreshControl?.addTarget(self, action: #selector(loadData), for: .valueChanged)
- 在tableView的delegate方法中设置上拉刷新和下拉加载
// 在显示最后一行的时候上拉刷新 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { // 1.判断是不是最后一行 let row = indexPath.row // 行 let section = tableView.numberOfSections - 1 // 最后一组 if row < 0 || section < 0 { return } let count = tableView.numberOfRows(inSection: section) // 最后一点组的的行数 if row == (count - 1) && !isPullup { isPullup = true loadData() } }
- 子类实现loadData()方法加载自己的数据
/// 加载数据 override func loadData() { // 异步延时加载数据 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
for i in 0..<10 { if self.isPullup { self.statusList.append("上拉\(i)") }else { self.statusList.insert(i.description, at: 0) } } self.isPullup = false self.refreshControl?.endRefreshing() self.tableView?.reloadData() }}
PS:到这里,基类tableView就基本设置好了### 2.设置用户未登录时的访客视图2.1.这是一个用户标记,判断用户是否登录
/// 用户登录标记 var userLogon = false
2.2 抽取一个继承自UIView的VisitorView - 声明需要的属性
// MARK: - 控件 // icon lazy var iconView:UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_image_smallicon")) // maskview lazy var maskIconView:UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_mask_smallicon")) // house lazy var houseView:UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_image_house")) // label lazy var tipLabel:UILabel = UILabel.cz_label(withText: "关注一些人,什么东西,关注一些人,什么东西,关注一些人,什么东西", fontSize: 14, color: UIColor.darkGray) // leftBtn lazy var registorBtn:UIButton = UIButton.cz_textButton("注册", fontSize: 16, normalColor: UIColor.orange, highlightedColor: UIColor.black, backgroundImageName: "common_button_white_disable") // rightBtn lazy var loginBtn:UIButton = UIButton.cz_textButton("登录", fontSize: 16, normalColor: UIColor.darkGray, highlightedColor: UIColor.black, backgroundImageName: "common_button_white_disable")
- 取消autoresiziong,使用iOS原生的自动布局设置界面(这里只列出一个控件的代码)
// 2.取消autoresiziong for v in subviews { v.translatesAutoresizingMaskIntoConstraints = false } // 3.自动布局 let margin:CGFloat = 20; // iconView addConstraint(NSLayoutConstraint(item: iconView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0)) addConstraint(NSLayoutConstraint(item: iconView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: -60))
```####PS: 对于iOS 原生的自动布局:```view1.attr1 = view2.attr2 * multiplier + constant// view1的某个属性值 = view2的某个属性值的 multiplier 倍 + 偏移量 constant// 在定义宽高属性的时候将 toItem 参数设置为 nil即可```- 用VFL来写的话,代码如下:```// maskIconView // views 是VFL 中控件名字和实际控件的名字映射 // metrics 是VFL 中常数的映射关系 let viewDict = ["maskIconView":maskIconView,"registorBtn":registorBtn] as [String : AnyObject] let metrics = ["spacing":20] addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[maskIconView]-0-|", options: [], metrics: nil, views: viewDict)) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[maskIconView]-(spacing)-[registorBtn]", options: [], metrics: metrics, views: viewDict))```2.3 设置圆圈转动动画```// 旋转动画private func startAnimation() { let ani = CABasicAnimation(keyPath: "transform.rotation") ani.toValue = 2 * M_PI ani.repeatCount = MAXFLOAT ani.duration = 15 ani.isRemovedOnCompletion = false iconView.layer.add(ani, forKey: nil)}```
3.设置视图数据
3.1 声明一个字典属性,通过disSet方法实现对访客视图数据的加载
```// MARK: - 设置访客视图信息// 访客视图信息字典var visitorInfo : [String:String]? { didSet { // 1. 取字典信息 guard let imageName = visitorInfo?["imageName"], let message = visitorInfo?["message"] else { return } // 2. 设置消息 tipLabel.text = message // 3. 设置图片 (通过图片名字判断是否为主页) if imageName == "" { startAnimation() return } iconView.image = UIImage(named: imageName) houseView.isHidden = true maskIconView.isHidden = true }}```
3.2 修改创建每个视图时的字典信息,添加visitorView信息
```// 首页["clsName":"XQWBHomeViewController", "title":"首页", "imgName":"home", "visitorInfo":["imageName":"", "message":"关注一些人,回这里看看有什么惊喜"]]```
3.3 参考淘宝等APP,tabbar图片在一些特殊的时间会变,修改tabbar信息的获取方式 ####大致流程图如下所示: - 建立AppDelegate的extension,获取服务器信息
```private extension AppDelegate { func loadAppInfo() { // 1. 模拟异步 DispatchQueue.global().async { // 1. url let url = Bundle.main.url(forResource: "main.json", withExtension: nil) // 2. data let data = NSData(contentsOf: url!) // 3. 写入磁盘 let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] let jsonPath = (docDir as NSString).appendingPathComponent("main.json") data?.write(toFile: jsonPath, atomically: true) print("程序加载完毕\(jsonPath)") } }}```- 修改主页面创建子控制器逻辑```// 设置所有字控制器func setupChildControllers() { // 获取沙盒路径 let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] let jsonPath = (docDir as NSString).appendingPathComponent("main.json") // 加载data var data = NSData(contentsOfFile: jsonPath) // 判断data是否为空 if data == nil { let path = Bundle.main.path(forResource: "main.json", ofType: nil) data = NSData(contentsOfFile: path!) } // 反序列化 // 从bundle加载json guard let array = try?JSONSerialization.jsonObject(with: data as! Data, options: []) as! [[String:AnyObject]] else { return } // 遍历数组,创建控制器 var arrayM = [UIViewController]() for dict in array { arrayM.append(controller(info: dict as [String : AnyObject])) } viewControllers = arrayM}```