AsyncDisplayKit
Facebook发布了其iOS UI框架AsyncDisplayKit(ASDK)1.0正式版,这个框架被用于Facebook自家的应用Paper中,能够提高UI的流畅性并缩短响应时间。
下载和使用
你可以使用CocoaPods来安装AsyncDisplayKit,在Podfile中添加:
pod 'AsyncDisplayKit'
OC中导入框架header,如果用Swift则可以创建Objective-C bridging header:
#import <AsyncDisplayKit/AsyncDisplayKit.h>
概述
AsyncDisplayKit(ASDK)的基本单元是node,ASDisplayNode是UIView之上的抽象层,同时也是CALayer的抽象层。和只能被用在主线程的视图不同,nodes是线程安全的:你能并行的实例化并设置整个node层级,并且在后台线程里运行。
为了保证它的用户界面的流畅性和响应性,你的app渲染帧率应该和iOS基准保持同步,即60帧每秒。这意味着主线程对每一帧有60分之一的时间来推送,也就是说大约要在16毫秒内执行所有的布局和绘制代码。而由于系统的性能开销,在导致丢帧之前,你的代码通常只有不到10毫秒的时间来执行。
AsyncDisplayKit让你将图像解码、调整文字大小并渲染,以及其他高耗时的UI操作移出主线程。当然它还有其他的一些功能,你可以在官方文档中探索。
作为视图直接替代的Node
如果你之前处理过视图,那么你已经知道如何使用node了。Node的API也类似于UIView,不过更方便。比如,你能直接读取公共的CALayer属性。如果想添加一个node到现有的视图或层级,使用node.view或node.layer。
AsyncDisplayKit包括一些强力的组件:
· ASDisplayNode. UIView的副本 —一个子类,用来自定义node。
· ASControlNode. 类似于UIControl —用来制作按钮的子类。
· ASImageNode. 类似于UIImageView —异步的解码图像资源。
· ASTextNode. 类似于UITextView — 基于TextKit构建,支持富文本的全部特性。
· ASTableView. UITableView子类,用于支持node。
你可以将这些用作UIKit副本的直接替代。即便ASDK在完整的基于node的层级下工作十分高效,使用node替代独立视图能够更加的提高性能。
让我们来看一个例子。
我们一开始在主线程中异步的使用node——和你平常使用视图的方式一样。我们的代码和自定义视图控制器-loadView的实现差不多:
_imageView = [[UIImageView alloc] init]; _imageView.image = [UIImage imageNamed:@"hello"]; _imageView.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f); [self.view addSubview:_imageView];
我们能使用如下基于node的代码来替代它:
_imageNode = [[ASImageNode alloc] init]; _imageNode.backgroundColor = [UIColor lightGrayColor]; _imageNode.image = [UIImage imageNamed:@"hello"]; _imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f); [self.view addSubview:_imageNode.view];
这并没有利用ASDK的异步调整大小和布局的功能,但已经有所改进了。第一段代码在主线程解码hello.png,第二段则在后台线程解码图像,并可能利用不同的CPU核心。
(注意我们在node中设置了占位符的背景颜色,它会占据屏幕直到真正的内容出现。这种做法对于图像很好,但不太适用于文字——人们期望文字能直接展示,图片则允许有加载延迟。我们后面会讨论如何改进的技术。)
node按钮
ASImageNode和ASTextNode都继承了ASControlNode,所以你能将它们当做按钮使用。假设我们在开发音乐播放器,并且希望添加(非拟物化的,iOS 7风格)随机播放按钮。

我们的视图控制器代码将和下面的差不多:
- (void)viewDidLoad { [super viewDidLoad]; // attribute a string NSDictionary *attrs = @{ NSFontAttributeName: [UIFont systemFontOfSize:12.0f], NSForegroundColorAttributeName: [UIColor redColor], }; NSAttributedString *string = [[NSAttributedString alloc] initWithString:@"shuffle" attributes:attrs]; // create the node _shuffleNode = [[ASTextNode alloc] init]; _shuffleNode.attributedString = string; // configure the button _shuffleNode.userInteractionEnabled = YES; // opt into touch handling [_shuffleNode addTarget:self action:@selector(buttonTapped:) forControlEvents:ASControlNodeEventTouchUpInside]; // size all the things CGRect b = self.view.bounds; // convenience CGSize size = [_shuffleNode measure:CGSizeMake(b.size.width, FLT_MAX)]; CGPoint origin = CGPointMake(roundf( (b.size.width - size.width) / 2.0f ), roundf( (b.size.height - size.height) / 2.0f )); _shuffleNode.frame = (CGRect){ origin, size }; // add to our view [self.view addSubview:_shuffleNode.view]; } - (void)buttonTapped:(id)sender { NSLog(@"tapped!"); }
这段代码能正常工作。不幸的是,这个按钮只有14.5个像素点高,离标准的44x44最小点击尺寸相距甚远,因此很难点击到。我们能够通过为 text node创建子类,并且覆盖-hitTest:withEvent:来解决这个问题。我们甚至能强制text view在布局中的最低高度,但如果有更优雅的解决办法不是更好吗?
// size all the things /* ... */ // make the tap target taller CGFloat extendY = roundf( (44.0f - size.height) / 2.0f ); _shuffleNode.hitTestSlop = UIEdgeInsetsMake(-extendY, 0.0f, -extendY, 0.0f);
就是这样!Hit-test slops在所有node中都能正常工作,并且是一个展示这个新的抽象层能干什么的极好的示例。
后面还会讲如何自定义node、异步的工作方式、最大限度的利用AsyncDisplayKit等,感兴趣的可以查看官方文档。
AsyncDisplayKit的更多相关文章
- [转]AsyncDisplayKit 教程:达到 60 FPS 的滚动帧率
[原文:https://github.com/nixzhu/dev-blog/blob/master/2014-11-22-asyncdisplaykit-tutorial-achieving-60- ...
- [翻译] AsyncDisplayKit
AsyncDisplayKit AsyncDisplayKit is an iOS framework that keeps even the most complex user interfaces ...
- AsyncDisplayKit技术分析
转载请注明出处:http://xujim.github.io/ios/2014/12/07/AsyncDisplayKit_inside.html ,谢谢 前言 Facebook前段时间发布了其iOS ...
- 分析facebook的AsyncDisplayKit框架,async-display使用async-transaction
上一篇<分析facebook的AsyncDisplayKit框架中的Transaction的工作原理>介绍了fb的asdk的异步事务ASAsyncTransaction,本篇介绍其在asd ...
- 分析facebook的AsyncDisplayKit框架中的Transaction的工作原理
在AsyncDisplayKit框架中有一个_ASAsyncTransaction模块,用于AsyncDiplayNode的异步事务,使用了dispatch_group实现. 主要目的是将operat ...
- AsyncDisplayKit编译和使用注意事项
Facebook开源框架,在github上可下载到.首先要编译AsyncDisplayKit库项目,有可能会出现下面错误: cocoaPods是基于ruby的项目版本控制软件,如果是ruby新手就会不 ...
- UML分析AsyncDisplayKit框架-ASMuplexImageNode异步下载时序图。
PS:博客园图片服务器不正常工作,数据上传后服务器返回http500,园方迟迟还没解决. 我从2016-01-18 05:52向园方反馈问题-请问博客园的图片服务器有在正常运行吗,至此时2016-01 ...
- iOS开发之多种Cell高度自适应实现方案的UI流畅度分析
本篇博客的主题是关于UI操作流畅度优化的一篇博客,我们以TableView中填充多个根据内容自适应高度的Cell来作为本篇博客的使用场景.当然Cell高度的自适应网上的解决方案是铺天盖地呢,今天我们的 ...
- 【转】GitHub 排名前 100 的安卓、iOS项目简介
GitHub Android Libraries Top 100 简介 排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不 ...
随机推荐
- VMware NAT模式下,公司代理下上网 续
这是在非公司环境下,VMware NAT 静态IP模式下上网 由于公司的限制,可能需要通过proxy上网. 下面是我在公司的配置(参考其他) 1. 修改 /etc/environment http_p ...
- Module not found: Error: Can't resolve ' vue-resource'
问题: 在学习vue的过程中出现了这个问题,说明VueResource模块没有安装. 解决方法: 打开终端,进入当前项目所在目录,输入指令 npm install vue-resource --sav ...
- java 根据省份证号-判断省份-性别-生日
package com.nf147.manage.Test; import java.text.ParseException; import java.text.SimpleDateFormat; i ...
- Java源码阅读-Integer(基于jdk1.8)
public final class Integer extends Number implements Comparable<Integer> Integer 由final修饰了,所以该 ...
- mysql修改数据表某列的配置
alter table 表名 modify column 字段名 类型;alter table 表名 drop column 字段名
- linux系统PS命令,按CPU、内存使用率对进程排序
https://blog.csdn.net/weixin_42123737/article/details/90081318
- zabbix分布式监控环境搭建
本次测试主要是在 centos 系统环境实践,测试内容:集群多台服务器资源监控做后续铺垫.zabbix的简介和自身的特点.在这就不阐述了 查询防火墙状态service iptables status停 ...
- 屏蔽ffmpeg命令的所有提示
有时候需要隐蔽的执行ffmpeg不希望输出任何日志,提示.这个时候只需要多添加这个参数即可 -loglevel quiet
- EasyHook(一)
前言 在说C# Hook之前,我们先来说说什么是Hook技术.相信大家都接触过外挂,不管是修改游戏客户端的也好,盗取密码的也罢,它们都是如何实现的呢? 实际上,Windows平台是基于事件驱动机制的, ...
- JS调用服务器端方法
javascript函数中执行C#代码中的函数:方法一:1.首先建立一个按钮,在后台将调用或处理的内容写入button_click中; 2.在前台写一个js函数,内容为document. ...