节点容器
在容器中使用Nodes
AsyncDisplayKit有以下几种 Container
ASDK Node Container | UIKit Equivalent |
---|---|
ASCollectionNode | 代替UIKit的 UICollectionView
|
ASPagerNode | 代替UIKit的 UIPageViewController
|
ASTableNode | 代替UIKit的 UITableView
|
ASViewController | 代替UIKit的 UIViewController
|
ASNavigationControllerv | 代替UIKit的 UINavigationController ,遵循ASVisibility 协议 |
ASTabBarController | 代替UIKit的 UITabBarController ,遵循ASVisibility 协议 |
Node Container的优势
Node Container
可以自动地管理node
的智能预加载,它会保证node
的的布局计算、数据获取、解码和渲染会以异步的方式进行。
Node的子类
AsyncDisplayKit提供了以下几种node
。
相对UIKit的组件来说 node
最大的改进就是将所有布局和显示都放在子线程,因此主线程就能够即时地响应各种事件。
ASDK Node | UIKit Equivalent |
---|---|
ASDisplayNode | 代替UIKit的 UIView ,其他的node都继承于它 |
ASCellNode | 代替UIKit的 UITableViewCell 和 UICollectionViewCell ,用在 ASTableNode , ASCollectionNode 和 ASPagerNode 中 |
ASScrollNode | 代替UIKit的 UIScrollView ,这个 node 用在自定义滚动区域上非常有用 |
ASEditableTextNode | 代替UIKit的 UITextView
|
ASTextNode | 代替UIKit的 UILabel
|
ASImageNode | 代替UIKit的 UIImage
|
ASNetworkImageNode | |
ASMultiplexImageNode | |
ASVideoNode | 代替UIKit的 AVPlayerLayer
|
ASVideoPlayerNode | 代替UIKit的 UIMoviePlayer
|
SControlNode | 代替UIKit的 UIControl
|
ASButtonNode | 代替UIKit的 UIButton
|
ASMapNode | 代替UIKit的 MKMapView
|
AsyncDisplayKit 中的 node
相比UIKit中的组件更先进而且更方便。比如 ASNetworkImageNode
可以自动地加载和进行内存管理,而且还支持逐步加载Jpeg和动态gif图片。
node
的层级结构如下
上图中蓝色高亮的node是对UIKit元素的封装而成。比如 ASScrollNode
封装自 UIScrollView
, ASCollectionNode
封装自 UICollectionView
,ASMapNode
在实时地图模式中就是 UIMapView
封装。
基本重载方法
创建子类时,子类是
ASViewController
还是ASDisplayNode
有很大的区别。这感觉上是显而易见的,但是有的区别是很微妙的,所有也需要特别注意。
ASDisplayNode
如果你使用的 node
组件类型于 UIView
的子控件,就必须注意下面几条准则以确保你充分发挥了这个框架的潜力, node
也能很好的显示。
-init
当使用 nodeBlock
的时候这个方法是在子线程进行的。但是,如何 -init
没有运行完,其他方法就无法运行,所以这个方法永远不要上锁。
最重要的是你的 init
方法一定要能在任何队列中调用。尤其是不要在初始化的时候初始化任何 UIKit
控件、点击 node
的 view
或者 layer
或者添加任何手势。这些事情应该放在 -didLoad
中。
-didLoad
这个方法在概念上类似于 UIViewController
的 -viewDidLoad
方法,它代表着后台的 view
已经被加载完成了。要确保它是在主线程中执行的,在这个方法中很适合处理 UIKit
的各种操作(比如添加手势,点击 view
或者 layer
,初始化 UIKit
组件)。
-layout
在这个方法里调用 super
之后,布局规则对象会把所有的子节点都计算并且定位好,所以这个时间点是你手动进行布局所有子view的时机。或许更有用的是,有时候你想手动布局,但并不太容易创建一个布局规则对象,或者有时候你不想等所有子节点布局完毕,而只是很简单的手动设置frame,如果是这样的话,就在这个方法里写。
layoutSpecThatFits
这个方法就是用来建立布局规则对象,产生 node
大小以及所有子 node
大小的地方,你创建的布局规则对象一直持续到这个方法返回的时间点,经过了这个时间点后,它就不可变了。尤其重要要记住的一点事,千万不要缓存布局规则对象,当你以后需要他的时候,请重新创建。
ASViewController
ASViewController
是 UIViewController
的子类,包含了管理 node
的特性。因此它的所有方法一定要在主线程中使用。
-init
这个方法只调用一次,是在 ASViewController
的生命周期的最开始的时候调用。在它初始化的过程中,不要使用 self.view
或者 self.node.view
,它会强制 view
被提前创建。这些事情应该在 viewDidLoad
中完成。
ASViewController
的初始化方法是 initWithNode:
,代码如下所示。一个 ASViewController
管理节点就像 UIViewController
管理 view
一样,但是初始化的过程有小小的差异。
- (instancetype)init
{
_pagerNode = [[ASPagerNode alloc] init];
self = [super initWithNode:_pagerNode];
// setup any instance variables or properties here
if (self) {
_pagerNode.dataSource = self;
_pagerNode.delegate = self;
}
return self;
}
-loadView
建议不要使用这个方法,因为它相对于 viewDidLoad
来说没有明显的优势反而有很多不足的地方。但如果你不去设置 self.view
的属性就没什么问题。调用 [super loadView]
它就会执行 node.view
。
-viewDidLoad
它会在 ASViewController
的生命周期的最开始调用,仅次于 -loadView
。这是你使用节点的 view
最早的时机。在这个方法里适合放只执行一次并且要使用 view/layer
的代码,比如加手势。
布局的代码千万不要放在这个方法里,因为界面发生改变也不会再调用这个方法重新布局。
-viewWillLayoutSubviews
这个方法调用的时机和节点 -layout
方法调用的时机一样,它可以被执行很多次。只要它的节点被改变(比如旋转,分屏,显示键盘)或者继承()都会立即被调用。