IOS中使用AsynDisplayKit优化项目

前言

在学习别人文章的时候做一个记录,免得在需要的时候找不到。本文主要记录原理性的内容,也会包含一些代码,具体使用请看文章。先把文章地址贴出来

AsyncDisplayKit2.0教程上 

AsyncDisplayKit2.0教程下

这篇文章中的例子可以直接运行,另外的可以自己查看 AsyncDisplaykit2.0

安装

项目使用CocoaPods安装AsynDisplayKit,在Pod文件中输入安装

source 'https://github.com/CocoaPods/Specs.git'

target "AsyncDisplayKitForMit" do

pod 'AsyncDisplayKit'

end

使用介绍

在主线程中进行的一些大量操作包括:

计算大小和布局:包括 -heightForRowAtIndexPath: 或对 UILabel 上进行 -sizeThatFits 调用,以及大量的自动布局约束的解析。

图片解码:在一个 Image View 上使用 UIImage 就意味着要进行图片数据的解码。

绘图:复杂文本以及手动绘制渐变色和阴影。

对象生命周期:创建、操作和销毁系统对象(比如创建一个 UIView)。

在正确使用的情况下,AsynDisplayKit 默认允许你以异步方式操作所有的计算大小、布局和绘图操作。不需要进行任何其它的优化,App 就能够大量减少需要在主线程上进行的工作。

ASDisplayNode 简介

ASDisplayNode 是 ASDK 的核心类,甚至可以说是“心脏”,就像 MVC 中的 view,可以看做是另一种 UIView 或 CALayer。理解一个“节点”对象的最好方法是参考 UIView 和 CALayer 的关系,你对此应该很熟悉了。

在一个 iOS App 中,屏幕上的每一个对象都表示了一个 CALayer 对象。UIView 私底下会创建和拥有一个 CALayer,通过这个 CALayer 来感知触摸或其他功能。UIView 自身并不是 CALayer 子类。相反,它包含了一个 CALayer 对象,并为它添加了一些功能。

这种概念也沿袭进了 ASDisplayNode:你可以认为它包含了一个 view,就好比 view 包含了一个 layer。

将节点通过一个普通的 View 放到表格上,最终使它们能够从后台队列中创建和配置,默认情况下,它们会被异步渲染。

幸运的是,这个 API 处理节点的方式和使用 UIView 或 CALayer 差不多。所有的 View 属性都可以在节点类上找到相同的属性。你还可访问底层的 view 或 layer——就像你可以通过 .layer 访问 UIView 的 layer 一样。

节点容器

要让节点对象尽可能地提升性,必须将它和 4 个容器类协同工作。 

这 4 个容器类分别是:

ASViewController: 一个 UIViewController 子类,允许你创建节点并进行管理。

ASCollectionNode 和 ASTableNode: 对应于 UICollectionView 和 UITableView 的 Node 子类,封装了其底层细节。

ASPagerNode: 一个 ASCollectionNode 子类,封装了扫动手势,对应于 UIKit 的 UIPageViewController。

这也太简单了,但真正的秘密其实来自于 ASRangeController,这 4 个类都会通过它来影响所包含的节点的行为。现在,请听我说,暂且将那些内容保留到后面解释。

使用

a:导入框架 #import <AsyncDisplayKit/AsyncDisplayKit.h>

b:声明tabelNode属性

@property (strong, nonatomic) ASTableNode *tableNode;

c:初始化容器,设置 TableNode 的数据和委托

和 UITableView 一样,ASTableNode 也使用了数据源和委托来获得相关信息。Table Node 的 ASTableDataSource 和 ASTableDelegate 协议和 UITableViewDataSource 和 UITableViewDelegate 协议非常类似。事实上,它们的方法定义都很像,比如 -tableNode:numberOfRowsInSection:。当然,这两套协议也不是完全没有区别,因为 ASTableNode 的行为和 UITableView 多少还是有一点不同。

 _tableNode = [[ASTableNode alloc]initWithStyle:UITableViewStylePlain];

   self.tableNode.dataSource = self;

   self.tableNode.delegate = self;

   self.tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone;

   [self.view addSubnode:self.tableNode];

d:然后,修改 -viewWillLayoutSubviews 方法:

- (void)viewWillLayoutSubviews {  

[superviewWillLayoutSubviews];

self.tableNode.frame = self.view.bounds;

}

到现在相当于创建好了tableview并设置好其frame,显示cell需要再实现其数据源方法

e:遵守数据源相关协议

@interface AnimalTableController()<ASTableDataSource,ASTableDelegate>

f:实现两个显示前重要的协议

- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { //返回多少行

  return self.animals.count;

}

然后,ASTableNodes 返回 cell 的方式和 UITableView 有所不同。将 -tableView:cellForRowAtIndexPath: 方法替换为:

 (ASCellNodeBlock)tableNode:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath*)indexPath {

RainforestCardInfo *animal  = self.animals[indexPath.row];

ASCellNode *(^cellNodeBlock)() = ^ASCellNode *() {

        TableViewNodeCell *cellNode = [[TableViewNodeCell alloc] initWithHaiTao:haiTaoStyle];

        return cellNode;

    };

return cellNodeBlock;

}

代码解释如下:

TableViewNodeCell继承自ASCellNode,一个 ASCellNode 等同于 UITableViewCell 或 UICollectionViewCell。尤其要注意这个方法返回的是一个 ASCellNodeBlock。因为一个 ASTableNode 在内部维护了所有的 cell,为每个 cell 的 Index Path 指定了一个块,这样当需要的时候就能够异步地初始化所有 cell。 

首先,你需要获得一个数据模型对象,以便渲染这个 cell。这已经是固定的套路了。获取数据,然后将它传给后面的闭包。IndexPath 在闭包中不需要,这个例子中在闭包被调用之前数据就会先发生改变。

然后返回一个闭包,闭包中返回的类型必须是 ASCellNode。

不需要关心 cell 重用的问题,因此只需要实例化一个 cell。注意,你返回的是一个 CardNode 而不是 CardCell。

这里有一点要注意。你可能也注意到了,使用 ASDK 的时候 cell 不会进行重用。

g:相信你也知道了,在使用 UITableView 的时候通常都需要实现一个 -tableView:heightForRowAtIndexPath: 方法。这是因为 UIKit 是通过这个委托方法来计算每个 cell 的高度的。

ASTableDelegate 中没有 -tableView:heightForRowAtIndexPath: 方法。如果使用 ASDK, 所有的 ASCellNodes 都自己负责计算它们的大小。不需要提供一个固定的高度,你可以为每个 cell 指定一个最大尺寸和最小尺寸。这个例子中,你需要让每个 cell 至少占据屏幕 2/3 的高度。

现在我们暂时不讨论这个,细节会在第二部分进行讨论。 

现在,将 -tableView:heightForRowAtIndexPath: 方法替换为:

- (ASSizeRange)tableView:(ASTableView*)tableNode  constrainedSizeForRowAtIndexPath:(NSIndexPath*)indexPath { 

 CGFloat width = [UIScreen mainScreen].bounds.size.width;  

CGSizemin= CGSizeMake(width, ([UIScreen mainScreen].bounds.size.height/3) *2);  CGSizemax= CGSizeMake(width, INFINITY);

returnASSizeRangeMake(min,max);

}

//剩下的重要内容就在自定义ASCellNode中了,包括里面的控件创建与布局。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容