AsyncDisplayKit 系列教程 —— 添加一个 UIActivityIndicatorView 到 ASCellNode
来源:互联网 发布:小米note查看网络制式 编辑:程序博客网 时间:2024/06/04 23:18
原理
添加一个自定义的 View 到 ASCellNode 中并不是一件容易的事情,和添加一个原生 ASDisplayNode 不一样的是,你需要自行处理 Cell 被重新渲染时的状态。
我们先描述一下 ASCellNode 的生命周期
一个 ASDisplayNode 在 init 至 layout 的过程中,都只是属性的操作,这个操作并不会生成任何实际的 UIView,这也是为什么 AsyncDisplayKit 高效的原因之一,将 UIView 实例化的过程推迟至最终使用时。
一个 ASDisplayNode 中的 UIView 生成、清除的时机由 ASTableView决定, ASTableView 总是保证只保留用户所看到的 Node 存在 UIView 实例。
因此, ASCellNode 中的 subnode 也同时遵循上图的生命周期。
示例
在 AsyncDisplayKit 系列教程 —— ASTableView 一文中,已经演示过如何添加一个 ASImageNode 和 ASTextNode。
现在,我们演示一下如何添加一个 UIActivityIndicatorView 到 Cell 中, UIActivityIndicatorView 并没有对应的 ASDisplayNode 子类实现。因此,我们需要创建一个 ASDisplayNode ,使用block方法返回 UIActivityIndicatorView。
let activityIndicator = ASDisplayNode { () -> UIView! in let view = UIActivityIndicatorView(activityIndicatorStyle: .Gray) view.backgroundColor = UIColor.clearColor() view.hidesWhenStopped = true return view}
之后,就可以像普通的 ASDisplayNode 一样将其添加至 subnode 中。
override init!() { super.init() addSubnode(activityIndicator)}
一套完整的代码如下图所示
//// ViewController.swift// AsyncDisplayKit-Issue-4//// Created by 崔 明辉 on 15/11/28.// Copyright © 2015年 Pony.Cui. All rights reserved.//import UIKitclass ViewController: UIViewController, ASTableViewDataSource, ASTableViewDelegate { let tableView = ASTableView() deinit { tableView.asyncDelegate = nil // 记得在这里将 delegate 设为 nil,否则有可能崩溃 tableView.asyncDataSource = nil // dataSource 也是一样 } override func viewDidLoad() { super.viewDidLoad() tableView.asyncDataSource = self tableView.asyncDelegate = self self.view.addSubview(tableView) } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() tableView.frame = view.bounds } func numberOfSectionsInTableView(tableView: UITableView!) -> Int { return 1 } func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return 100 } func tableView(tableView: ASTableView!, nodeForRowAtIndexPath indexPath: NSIndexPath!) -> ASCellNode! { let cellNode = CustomCellNode() cellNode.startAnimating() return cellNode }}class CustomCellNode: ASCellNode { let activityIndicator = ASDisplayNode { () -> UIView! in let view = UIActivityIndicatorView(activityIndicatorStyle: .Gray) view.backgroundColor = UIColor.clearColor() view.hidesWhenStopped = true return view } override init!() { super.init() addSubnode(activityIndicator) } func startAnimating() { if let activityIndicatorView = activityIndicator.view as? UIActivityIndicatorView { activityIndicatorView.startAnimating() } } override func calculateSizeThatFits(constrainedSize: CGSize) -> CGSize { return CGSize(width: constrainedSize.width, height: 44) } override func layout() { activityIndicator.frame = CGRect(x: self.calculatedSize.width / 2.0 - 22.0, y: 11, width: 44, height: 44) }}
我们指定生成 100 个 Cell,每个 Cell height = 44,运行这个Demo你可以看到菊花已经显示在界面上了。
坑
等等,看上去好像没什么问题,滑到最下面再滑回去,你会发现,什么?菊花没了!
为什么会这样!
还记得我们说过的,一个 Node 中的 UIView 是会被清除、重新生成的吗? 在滑动到下方的时候, Node 中的所有 UIView 都会被干掉,然后滑回来的时候,会被重新执行 Block 中的代码,然后重新添加到界面上。
这个时候,我们的 UIActivityIndicatorView 还没被执行 startAnimating() 方法。
要解决这个坑,也不是很难,只要在 Node 重新出现的时候,执行一下 startAnimating() 就可以了。
//// ViewController.swift// AsyncDisplayKit-Issue-4//// Created by 崔 明辉 on 15/11/28.// Copyright © 2015年 Pony.Cui. All rights reserved.//import UIKitclass ViewController: UIViewController, ASTableViewDataSource, ASTableViewDelegate { let tableView = ASTableView() deinit { tableView.asyncDelegate = nil // 记得在这里将 delegate 设为 nil,否则有可能崩溃 tableView.asyncDataSource = nil // dataSource 也是一样 } override func viewDidLoad() { super.viewDidLoad() tableView.asyncDataSource = self tableView.asyncDelegate = self self.view.addSubview(tableView) } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() tableView.frame = view.bounds } func numberOfSectionsInTableView(tableView: UITableView!) -> Int { return 1 } func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return 100 } func tableView(tableView: ASTableView!, nodeForRowAtIndexPath indexPath: NSIndexPath!) -> ASCellNode! { let cellNode = CustomCellNode() cellNode.startAnimating() return cellNode } // 实现这个 delegate func tableView(tableView: ASTableView!, willDisplayNodeForRowAtIndexPath indexPath: NSIndexPath!) { if let cellNode = tableView.nodeForRowAtIndexPath(indexPath) as? CustomCellNode { cellNode.resume() } }}class CustomCellNode: ASCellNode { let activityIndicator = ASDisplayNode { () -> UIView! in let view = UIActivityIndicatorView(activityIndicatorStyle: .Gray) view.backgroundColor = UIColor.clearColor() view.hidesWhenStopped = true return view } override init!() { super.init() addSubnode(activityIndicator) } // 使用 resume 方法调用 startAnimating func resume() { startAnimating() } func startAnimating() { if let activityIndicatorView = activityIndicator.view as? UIActivityIndicatorView { activityIndicatorView.startAnimating() } } override func calculateSizeThatFits(constrainedSize: CGSize) -> CGSize { return CGSize(width: constrainedSize.width, height: 44) } override func layout() { activityIndicator.frame = CGRect(x: self.calculatedSize.width / 2.0 - 22.0, y: 11, width: 44, height: 44) }}
扩展
使用同样的方法,可以添加任意类型 UIView 到 CellNode 中,这样就不需要被 AsyncDisplayKit 束缚我们的应用了。
相关的代码可以在这个链接中找到 https://github.com/PonyCui/AsyncDisplayKit-Issue-4
- AsyncDisplayKit 系列教程 —— 添加一个 UIActivityIndicatorView 到 ASCellNode
- AsyncDisplayKit 系列教程 —— 为什么要使用 AsyncDisplayKit
- AsyncDisplayKit 系列教程 —— 集成、示例
- AsyncDisplayKit 系列教程 —— ASTableView
- AsyncDisplayKit教程
- 把UIActivityindicatorView 添加到 UIAlertView里面
- 把UIActivityindicatorView 添加到…
- 【Web API系列教程】3.9 — 实战:处理数据(添加新条目到数据库)
- iOS——UIActivityIndicatorView
- AsyncDisplayKit 2.0 Objective-C 教程
- AsyncDisplayKit
- Asyncdisplaykit
- UIActivityIndicatorView,一个名字长到令人发指的控件
- [转]Ultra Fractal教程系列40——蒙版的学习06——添加一个蒙版图层
- cocoa touch——UIActivityIndicatorView
- ajax系列教程,从读取,修改,添加,到删除效果!
- 迁移到Office365教程系列——部署DirSync
- 添加一个Object-c的UI控件到cocos2d-x的c++代码中(object向c++转型系列教程1)
- AsyncDisplayKit 系列教程 —— 为什么要使用 AsyncDisplayKit
- 如何解决VS2015c4996的错误
- AsyncDisplayKit 系列教程 —— 集成、示例
- AsyncDisplayKit 系列教程 —— ASTableView
- C++学习一初始化列表的执行顺序
- AsyncDisplayKit 系列教程 —— 添加一个 UIActivityIndicatorView 到 ASCellNode
- 寒假学习之stm32(8)-----定时器输出PWM
- App_Code里的类引用问题
- 把项目的绝对路径,提取简化为一个公共标签
- 接口
- 图书管理系统之数据库访问层设计
- 01.java实现冷饮批发管理系统-页面设计之【登录页面】
- python技巧(15)
- AVL树相关的一些操作