前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

Texture

作者头像
拉维
发布2019-08-12 15:49:25
2.4K1
发布2019-08-12 15:49:25
举报
文章被收录于专栏:iOS小生活

Texture原名是AsyncDisplayKit,是Facebook的paper团队发布的一个基于UIKit的库,这个库能够将图片加载、布局计算以及UI渲染等操作均放在后台线程,进而可以极大地优化APP界面的流畅度

在之前的文章iOS的性能优化中我详细介绍了卡顿产生的原因,这里不做赘述,总结成一句话就是:GPU或者CPU的消耗过大,导致在一次同步信号之间没有准备完成,没有内容提交,导致掉帧。而Texture的最大特点就是能够极大地优化卡顿问题,其优化原理如下:

  1. 布局:iOS的Autolayout在性能上是存在瓶颈的,并且只能在主线程进行计算,因此Texture弃用了AutoLayout,自己设计了一套布局方式。
  2. 渲染:对于大量文本、图片等的渲染,UIKit组件只能在主线程进行,可能会造成GPU绘制的资源紧张;而ASDK会在后台异步绘制图层,不会阻塞主线程的运行。

实际上,ASDK的最大特点就是异步。将消耗时间的渲染、图片解码、布局计算、以及其他UI操作等等全部移除主线程,这样主线程就可以对用户的操作及时作出响应,进而达到流畅运行的目的

控件

上图是常见的UIView和CALayer的关系:View持有Layer用于展示,View本身会响应触摸事件。

上面两图展示了ASNode、UIView以及CALayer三者的关系。

Texture几乎封装了UIKit中的所有常用控件,二者的对应关系如下:

Nodes

Node Containers

子父类关系

ASDisplayNode

其作用等同于UIView,是所有Node的父类。需要注意的是,ASDisplayNode也拥有一个view属性,所以ASDisplayNode及其子类都可以通过这个view来添加UIKit控件,所以Texture可以和UIKit混用

代码语言:javascript
复制
- (void)viewDidLoad {
 //在UIKit中添加ASDisplayNode
 ASDisplayNode *displayNode = [[ASDisplayNode alloc] init];
    displayNode.frame = CGRectMake(10, 100, 200, 300);
    displayNode.backgroundColor = UIColor.redColor;
    [self.view addSubnode:displayNode];
 //在ASDisplayNode中添加UIKit的方式1
 UIView *subView1 = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 60, 60)];
    subView1.backgroundColor = UIColor.orangeColor;
    [displayNode.view addSubview:subView1];
 //在ASDisplayNode中添加UIKit的方式2
 ASDisplayNode *subNode2 = [[ASDisplayNode alloc] initWithViewBlock:^UIView * _Nonnull{
 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 100, 60, 60)];
        view.backgroundColor = UIColor.yellowColor;
 return view;
    }];
    [displayNode addSubnode:subNode2];
}

在ASDisplayNode中添加UIKit的方式2最终生成的是block返回的UIKit对象,但是外部表现的是ASDisplayNode。

ASCellNode

作用等同于UITableViewCell或者UICollectionViewCell,自带indexPath属性,有些时候很有用。

ASTextNode

作用等同于UILabel,与UILabel不同的是,ASTextNode必须通过attributedString来设置文字。

ASTextNode2

在ASTextNode的基础上修复了一些Bug。

ASImageNode

作用等同于UIImageView,但是只能设置静态图片,如果需要设置网络图片,那么需要使用ASNetworkImageNode。

ASNetworkImageNode

作用等同于UIImageView,当需要加载网络图片的时候会使用此类,Texture用的是第三方的图片加载库PINRemoteImage。ASNetworkImageNode并不支持gif,如果需要显示gif的话推荐使用FLAnimatedImage。

ASButtonNode

作用等同于UIButton,但是需要特别注意imageAlignment和contentSpacing这两个属性,如下:

代码语言:javascript
复制
    ASButtonNode *buttonNode = [[ASButtonNode alloc] init];
    buttonNode.frame = CGRectMake(10, 200, 100, 60);
    [buttonNode setTitle:@"按钮" withFont:[UIFont systemFontOfSize:16] withColor:UIColor.blackColor forState:UIControlStateNormal];
    [buttonNode setImage:[UIImage imageNamed:@"btnimgname"] forState:UIControlStateNormal];
 /*调整图片和文字的排列方式,有两个选择:
     *ASButtonNodeImageAlignmentBeginning,图片在前,文字在后
     *ASButtonNodeImageAlignmentEnd,文字在前,图片在后
     */
    buttonNode.imageAlignment = ASButtonNodeImageAlignmentEnd;

 //*调整图片和文字的间距
    buttonNode.contentSpacing = 10;
    [displayNode addSubnode:buttonNode];

ASTableNode

作用等同于UITableView,但是并未采用UITableView的重用机制。

并且,ASTableNode并没有像UITableView一样提供一个

- tableView: heightForRowAtIndexPath:

协议方法来决定每个cell的高度,而是由ASCellNode本身决定,这样的一个好处就是,可以很轻易地实现动态的高度

布局

AsyncDicplayKit拥有自己的一套成熟的布局方案,虽然语法比Masonry等(对AutoLayout的封装)要复杂,但是其性能却比AutoLayout好得不是一点点。

一、QuickStart(快速学习)

先来说一些基本概念。

1、LayoutSpecs(布局规则)

“LayoutSpecs”是“Layout Specifications”的缩写,没有物理存在。

LayoutSpecs是充当其他LayoutElements的容器,来解释这些子LayoutElements是如何相互关联的。

AsyncDisplayKit提供了ASLayout的几个子类,后面会有介绍。

从插入单个简单布局到更多更复杂的布局规则,变化堆放排列配置。

2、LatoutElements(布局元素)

LayoutSpecs包含并排列LayoutElements。

所有的ASDisplayNodes和ASLayoutSpecs都符合<ASLayoutElements>协议,这意味着你可以从LayoutNode和其他LayoutSpecs构成LayoutSpecs

3、组合LayoutSpecs和LayoutElements,创建复杂UI

通过下图我们可以看到如何将ASTextNode(黄色高亮)、ASVedioNode(顶部图像)和ASStackLayoutSpec(堆栈布局规则)组合来创建复杂布局。

使用ASCenterLayoutSpec(中心布局规则)和ASOverlayLayoutSpec(覆盖布局规则)来放置顶部ASVedioNode(顶部图像)。

4、一些Node需要设置初始大小

有一些元素,基于其可用内容,是有一个“固定大小”的,此时我们无需给其设置初始大小

例如,ASTextNode就可以根据其属性字符串计算其大小,其他具有固定大小的Node包括:

  • ASTextNode
  • ASTextNode2
  • ASImageNode
  • ASButtonNode

有一些Node在其外部资源加载完成之前,没有或者缺乏“固定大小”。

例如,在从URL下载图片之前,ASNetworkImageNode就不知道它的大小。这些种类还包括:

  • ASVedioNode
  • ASVedioPlayerNode
  • ASNetworkImageNode
  • ASEditableTextNode

缺乏初始固有大小的这些Node,必须设置它们的初始大小,使用ASRatioLayoutSpec(比例布局规则)、ASAbsoluteLayoutSpec(绝对布局规则)或者对象的size属性

二、Layout Examples(布局示例)

1,简单标题左右对齐

这种布局通过3个布局规则来实现:

一个垂直的ASStackLayoutSpec、一个水平的ASStackLayoutSpec和ASInsetLayoutSpec(用于插入整个标题)。

布局的组成(layout specs + Nodes)如下图所示:

代码如下:

2、图片上覆盖文本

这种是通过两个布局规则来实现的:

一个是用于插入文本的ASInsetLayoutSpec,还有一个是将插入文本覆盖在图片上的ASOverlayLayoutSpec。

代码如下:

3、图片上覆盖一个图标

可以通过绝对布局来实现,代码如下:

三、Layout Specs(布局规则)

以下ASLayoutSpec的子类,用于组成简单或复杂的布局:

  1. ASInsetLayoutSpec,插入布局
  2. ASOverlayLayoutSpec,覆盖布局
  3. ASBackgroundLayoutSpec,背景布局
  4. ASCenterLayoutSpec,中心布局
  5. ASRatioLayoutSpec,比例布局
  6. ASStackLayoutSpec,堆叠布局(Flexbox布局思想)
  7. ASAbsoluteLayoutSpec,绝对布局

你也可以子类化ASLayoutSpec,用以自定义一个ASLayoutSpec。

四、ASStackLayoutSpec(堆叠布局规则)

在AsyncDisplayKit的所有LayoutSpecs中,ASStackLayoutSpec是最强大的,ASStackLayoutSpec使用flexbox算法来确定其子节点的位置和大小,Flexbox旨在不同的屏幕尺寸上提供一致统一的布局。在堆叠布局中,以垂直或水平堆叠对齐item,堆叠布局可以是另一堆叠布局的子布局,这使得可以使用ASStackLayoutSpec来创建任何布局

ASStackLayoutSpec的属性介绍如下:

  1. direction,主轴的方向,指定子项的堆叠方向,默认是纵向。
  2. spacing,每个子元素之间的距离,即主轴上视图排列的间距。
  3. horizontalAlignment,水平对齐方式
  4. verticalAlignment,垂直对齐方式
  5. justifyContent,主轴上的排列方式,分五种:从前往后排列、居中排列、从后往前排列、间隔排列(两端无间隔)、间隔排列(两端有间隔)。
  6. alignItems,交叉轴上的排列方式
  7. flexWrap
  8. alignContent
  9. lineSpacing

Flexbox在ASDK中的工作方式与CSS在Web中的工作方式是相同的。

五、ASStackLayout布局元素属性

仅针对ASStackLayoutSpec布局的元素有效。

六、ASLayout布局元素属性

后记:本文只是对ASDK做了一个简单的介绍,通过本文可以对Texture有个初步了解,但是要想真正上手去做项目,还是要下一番功夫的,建议参考这篇文章:https://github.com/Luis-X/Facebook-Texture

以上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS小生活 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档