【翻译】Texture 布局--快速开始(Quickstart)

Texture 的布局 API 相比使用 UIKit 的自动布局有很多好处: 1. 快速:跟手动布局代码一样快,并且显著快于自动布局。 2. 异步和并行:布局可以在后台线程里计算,所以用户交互没有中断。 3. 可声明式:布局能声明为不可变的数据结构。这使得布局代码容易开发、文档化、代码审查、测试、调试、侧写和维护。 4. 可缓存:布局结果是不可变的数据结构,所以可以在后台提前计算并缓存以提升用户可感受到的表现。 5. 可扩展:易于在类之间分享代码。

July 7, 2017 -
ios texture 翻译

本文翻译自 TextureQuickstart 一文。

快速开始


动机和优点

UIKit 的自动布局(Auto Layout)在处理复杂视图结构时,消耗的资源呈指数级增加,所以创建了一个高性能的替代布局 API(Layout API)。Texture 的布局 API 相比使用 UIKit 的自动布局有很多好处:

  • 快速:跟手动布局代码一样快,并且显著快于自动布局。
  • 异步和并行:布局可以在后台线程里计算,所以用户交互没有中断。
  • 可声明式:布局能声明为不可变的数据结构。这使得布局代码容易开发、文档化、代码审查、测试、调试、侧写和维护。
  • 可缓存:布局结果是不可变的数据结构,所以可以在后台提前计算并缓存以提升用户可感受到的表现。
  • 可扩展:易于在类之间分享代码。

受 CSS Flexbox 的启发

熟悉 Flexbox 的人会注意到两个系统有很多相似。但是,Texture 的布局 API 没有重新实现全部的 CSS。

基本概念

Texture 的布局系统以两个基本概念为中心:

  1. 布局规格
  2. 布局元素

布局规格

布局规格,是“布局规范格式”的缩写,没有实体存在。布局规格作为容器(持有)其它布局元素,并用来了解这些相互关联的子布局元素。

Texture 提供了几个 ASLayoutSpec子类,从插入一个子(元素)的简单布局规范,到在变化中的堆里安排多个子(元素)的复杂布局规范。

布局元素

布局规格持有并安排布局元素。

全部 ASDisplayNodeASLayoutSpec 都符合 <ASLayoutElement> 协议。这意味你可以从两个 node 和其它布局规格组成(新)布局规格。酷!

ASLayoutElement 协议有几个属性可以用来创造特别复杂的布局。此外,布局规格有它们自己的属性可以用来调整布局元素的排列。

结合布局规格和布局元素来制作复杂的 UI

在这儿你可以看到 ASTextNode (以黄色突出显示)、ASVideoNode(上层图片)和 ASStackLayoutSpec (“布局规格堆”)是如何组合并创造出复杂布局的。

layout-spec-relationship-1

ASVideoNode(上层图片)之上放置播放图片是使用 ASCenterLayoutSpec(“居中布局规格”)和 ASOverlayLayoutSpec(“悬浮布局规格”)。

layout-spec-relationship-2

一些 node 需要尺寸集

一些元素基于它们立即可用的内容具有“固有尺寸”。例如,ASTextNode 能基于自身具备属性的字符串来计算它的大小。其它具有固有尺寸的 node 包括

  • ASImageNode
  • ASTextNode
  • ASButtonNode

所有其它 node 都没有固有尺寸或在外部资源被加载之前缺少固有尺寸。例如,ASNetworkImageNode 在图片已经从 URL 下载之前,都不知道它的大小。这些元素列表还包括

  • ASVideoNode
  • ASVideoPlayerNode
  • ASNetworkImageNode
  • ASEditableTextNode

这些缺少初始固有尺寸的 node 必须使用 ASRatioLayoutSpecASAbsoluteLayoutSpec 或者样式对象上的大小属性为其设置初始大小。

布局调试

在任何 ASDisplayNodeASLayoutSpec 上调用 -asciiArtString 都会返回表现对象及其子对象的 ascii art。可选项,如果你在任何 node 或布局规格上设置了 .debugName,这也会在 ascii art 里显示。见下面这个例子。

-----------------------ASStackLayoutSpec----------------------
|  -----ASStackLayoutSpec-----  -----ASStackLayoutSpec-----  |
|  |       ASImageNode       |  |       ASImageNode       |  |
|  |       ASImageNode       |  |       ASImageNode       |  |
|  ---------------------------  ---------------------------  |
--------------------------------------------------------------

你也可以打印输出在任何 ASLayoutElement(node 或布局规格) 上的布局对象。这在调试尺寸属性时特别有用。

(lldb) po _photoImageNode.style
Layout Size = min {414pt, 414pt} <= preferred {20%, 50%} <= max {414pt, 414pt}