资讯动态

Texture(AsyncDisplayKit)iOS 异步 UI 框架完全指南:节点模型、布局引擎与智能预加载

发布时间:2026/9/27 2:42:12 来源:尧图企业网站定制
移动开发UI组件【免费下载链接】TextureSmooth asynchronous user interfaces for iOS apps.项目地址https://gitcode.com/gh_mirrors/te/Texture点击查看免费下载Texture 是 Pinterest 在 AsyncDisplayKit 基础上持续演进的 iOS 异步 UI 框架其核心思想是用线程安全的node节点取代只能在主线程使用的UIView把图片解码、文本排版、布局测量与渲染等昂贵操作移出主线程从而保住 60fps 的流畅体验。本文以仓库根目录 README.md 为主体结合仓库内docs/_docs/官方文档与Source/源码实现系统讲解 Texture 的节点抽象、安装方式、节点与容器家族、声明式布局引擎以及智能预加载机制读完即可掌握将其集成进现有 iOS 应用并保持滚动流畅的完整方案。一、核心概念从 View 到 Node 的抽象Texture 的基本单元是node。ASDisplayNode是对UIView的抽象而UIView本身又是对CALayer的抽象。这条抽象链在源码头文件的注释中有明确表述见 Source/ASDisplayNode.hAnASDisplayNodeis an abstraction overUIViewandCALayerthat allows you to perform calculations about a view hierarchy off the main thread, and could do rendering off the main thread as well.与只能在主线程实例化和配置的 View 不同Node 是线程安全的你可以在后台线程上并行地实例化并配置整棵节点层级树而 UIKit 组件绝不允许这样做。如果你已经习惯使用 View那么使用 Node 几乎零成本迁移绝大多数方法都有对应的 node 版本绝大多数UIView/CALayer属性同样可用命名不一致时如.clipsToBounds与.masksToBoundsnode 默认采用UIView的命名唯一例外是 node 使用position而非center任何时候你都可以通过node.view或node.layer直接访问底层视图或图层但务必在主线程上进行。Node 与 View/Layer 的三层关系可以参考 node-view-layer.png 的示意理解这一抽象层级是掌握 Texture 一切特性的前提。二、性能原理为什么 Node 能保住 60fps要让界面保持流畅iOS 应用应以60 帧/秒为目标——这是业界公认的黄金标准。这意味着主线程每帧只有六十分之一秒的时间来推送画面也就是16 毫秒内必须完成全部布局和绘制代码而由于系统本身的开销你的代码通常只有不到 10 毫秒的执行时间否则就会丢帧。Texture 的核心价值在于把图片解码、文本测量与渲染、布局计算等昂贵的 UI 操作移出主线程让主线程始终空闲以响应触摸等用户交互事件。这一点在源码上也有支撑ASDisplayNode的初始化实现允许以 block 方式自定义底层视图/图层见 Source/ASDisplayNode.h 中的ASDisplayNodeViewBlock、ASDisplayNodeLayerBlock配合_ASDisplayLayer等实现Source/Details/_ASDisplayLayer.mmnode 的内容渲染可以发生在后台队列渲染完成后再以事务方式提交到主线程。三、安装与集成CocoaPods 与 CarthageTexture 同时支持 CocoaPods 和 Carthage详细说明见 docs/_docs/installation.md。无论采用哪种方式都需要导入框架头文件#import AsyncDisplayKit/AsyncDisplayKit.hSwift 用户则需要创建 Objective-C bridging header桥接头文件来引入该框架。需要注意podspec 中声明的模块名是AsyncDisplayKit见 Texture.podspec 的spec.module_name AsyncDisplayKit因此 import 时使用的是AsyncDisplayKit前缀尽管 CocoaPods 上的组件名是Texture。3.1 CocoaPods 方式在 Podfile 中添加target MyApp do pod Texture end然后彻底退出 Xcode在项目目录的终端中执行pod install升级 Texture 版本时执行pod update Texture安装完成后务必打开.xcworkspace工作区文件而不是.xcodeproj工程文件。仓库根目录的 Podfile 给出了真实项目中的完整依赖声明示例examples/下各示例工程如 ASDKgram也都带有可直接参考的 Podfile。3.2 Carthage 方式标准构建在 Cartfile 中添加以下行以获取最新 release分支github texturegroup/texture或者指定master分支github texturegroup/texture master然后执行carthage update该命令会把依赖拉取到Carthage/Checkouts目录并逐个构建。Texture 自带 Cartfile仓库根目录的 Cartfile 与 Cartfile.resolved来声明其依赖因此你只需这一行即可。构建完成后应在终端输出中确认Texture、PINRemoteImage、PINCache三个框架均已被拉取并构建成功。随后在 Xcode 的 Target → “General” → “Linked Frameworks and Libraries” 中把Carthage/Build目录下需要的框架拖入即可。注意Carthage light 模式Texture 暂不支持只手动添加工程文件的轻量用法原因是其依赖链中的PINCachePINRemoteImage的嵌套依赖还没有独立的工程文件而缺少PINRemoteImage与PINCache就无法获得 Texture 完整的图片功能集如渐进式 JPEG、动图与缓存管理。3.3 从 podspec 了解框架构成仓库根目录的 Texture.podspec 是了解框架构成的最佳入口当前版本 3.2.0最低支持 iOS/tvOS 14.0Subspec用途关键配置Core核心源码Source/**/*.{h,mm}编译器标志-fno-exceptionsPINRemoteImage远程图片下载与缓存依赖PINRemoteImage/iOS ~ 3.0.0与PINCacheIGListKit与 IGListKit 数据源集成依赖IGListKit ~ 4.0、IGListDiffKit ~ 4.0YogaYoga 布局支持宏YOGA1依赖Yoga ~ 2.0TextNode2新版文本节点宏AS_ENABLE_TEXTNODE0编译掉旧 TextNodeVideo视频节点链接 AVFoundation、CoreMedia宏AS_USE_VIDEO1MapKit地图节点链接 CoreLocation、MapKit宏AS_USE_MAPKIT1Photos/AssetsLibrary相册图片分别链接 Photos 与 AssetsLibrarydefault_subspecs Core, PINRemoteImage, Video, MapKit, AssetsLibrary, PhotosTexture.podspec意味着默认安装即包含远程图片、视频、地图与相册能力可按需裁剪。四、Node 家族覆盖绝大多数 UIKit 组件Texture 提供了一系列 node 来替代常用的 UIKit 组件完整对照见 docs/_docs/node-overview.mdTexture NodeUIKit 对应组件说明ASDisplayNodeUIView根节点所有其他 node 均继承自它ASCellNodeUITableViewCell/UICollectionViewCell用于ASTableNode、ASCollectionNode、ASPagerNodeASScrollNodeUIScrollView创建包含其他 node 的自定义可滚动区域ASEditableTextNode/ASTextNodeUITextView/UILabel可编辑与只读文本ASImageNode/ASNetworkImageNode/ASMultiplexImageNodeUIImageView本地图 / 网络图 / 多图源ASVideoNode/ASVideoPlayerNodeAVPlayerLayer/ 播放器视频渲染与播放控制ASControlNodeUIControl控件基类ASButtonNodeUIButton按钮ASMapNodeMKMapView地图展示与 UIKit 组件仅有粗略的对应关系不同node 通常提供更高级的特性与便利性。例如ASNetworkImageNode自动完成加载与缓存管理还支持渐进式 JPEG 和动图GIF。所有 node 的核心优势是布局与显示全部在非主线程完成见 docs/_docs/node-overview.md。所有 node 都继承自ASDisplayNode继承体系如 node-hierarchy.png 所示。图中蓝色标注的节点是对 UIKit 元素的同步包装例如ASScrollNode包装UIScrollViewASCollectionNode包装UICollectionViewASMapNode在liveMapMode下是MKMapView的同步包装。examples/AsyncDisplayKitOverview 示例工程对上述每个 node 都提供了基础实现是快速上手各类 node 的最佳参考。五、Node 容器把 Node 放进正确的位置强烈建议把 node 放入 node 容器中使用。最常见的错误是直接把 node 添加到现有 View 层级中——这几乎必然导致渲染时的闪烁。正确做法是把 node 作为某个容器 node 的子节点详见 docs/_docs/containers-overview.mdTexture Node 容器UIKit 对应组件说明ASCollectionNodeUICollectionView集合视图ASPagerNodeUIPageViewController分页视图ASTableNodeUITableView列表视图ASDKViewControllerUIViewController视图控制器用于承载 node 层级ASDKNavigationControllerUINavigationController实现ASVisibility协议ASTabBarControllerUITabBarController实现ASVisibility协议这些容器负责向所含 node 通报它们当前所处的状态以便数据尽可能高效地加载、节点尽可能高效地渲染。可以把容器类理解为 UIKit 与 Texture 之间的集成点。使用容器能获得什么容器会自动管理其下 node 的智能预加载也就是说节点布局测量、数据获取、解码与渲染都会异步完成。虽然不使用容器也能直接用 node但那样的话除非额外调用相关接口node 只有在真正上屏时才会开始渲染与 UIKit 行为一致容易导致性能退化与内容闪烁。对应源码位于 Source/ASCollectionNode.mm、Source/ASTableNode.mm、Source/ASPagerNode.mm、Source/ASDKViewController.mm 等文件中各容器的示例工程在各自的官方文档中均有标注。六、声明式布局引擎Layout Spec 取代 AutoLayoutTexture 的布局引擎基于CSS Box 模型FlexBox这是它与 UIKit 的 AutoLayout 差异最大的特性同时也是最有价值的特性之一详见 docs/_docs/layout-engine.md。参与这套系统的主要方式是在 node 子类中实现-layoutSpecThatFits:从内向外声明式地构建布局 spec最后返回包含全部子节点的顶层 spec。Objective-C 示例垂直堆叠布局子节点间距 4pt- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { ASStackLayoutSpec *verticalStack [ASStackLayoutSpec verticalStackLayoutSpec]; verticalStack.direction ASStackLayoutDirectionVertical; verticalStack.spacing 4.0; [verticalStack setChildren:_commentNodes]; return verticalStack; }Swift 对应写法override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) - ASLayoutSpec { let verticalStack ASStackLayoutSpec() verticalStack.direction .vertical verticalStack.spacing 4.0 verticalStack.children commentNodes return verticalStack }堆叠布局 spec 会在指定方向上、按指定间距把子节点依次排布功能与UIStackView类似但额外具备向后兼容性。6.1 ASLayoutable 协议与组合式布局Layout spec 的子节点可以是任何符合ASLayoutable协议的对象而所有 node 和所有 layout spec 都符合该协议。这意味着布局可以像积木一样组合例如给上面的堆叠布局加 8pt 内边距只需让该堆叠 spec 成为一个 inset spec 的子节点- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { ASStackLayoutSpec *verticalStack [ASStackLayoutSpec verticalStackLayoutSpec]; verticalStack.direction ASStackLayoutDirectionVertical; verticalStack.spacing 4.0; [verticalStack setChildren:_commentNodes]; UIEdgeInsets insets UIEdgeInsetsMake(8, 8, 8, 8); ASInsetLayoutSpec *insetSpec [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:verticalStack]; return insetSpec; }Swift 对应写法override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) - ASLayoutSpec { let verticalStack ASStackLayoutSpec() verticalStack.direction .vertical verticalStack.spacing 4.0 verticalStack.children commentNodes let insets UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) return ASInsetLayoutSpec(insets: insets, child: verticalStack) }布局 spec 的全部实现位于 Source/Layout 目录其中 ASStackLayoutSpec.mm、ASInsetLayoutSpec.mm 等文件对应ASStackLayoutSpec、ASInsetLayoutSpec等常用 specASLayoutElement.hSource/Layout/ASLayoutElement.h则定义了布局元素协议。更多布局 spec 类型与用法可参阅 docs/_docs/automatic-layout-basics.md 及docs/_docs/下layout2-*、automatic-layout-*系列文档。七、智能预加载Interface State 与 Range 控制器异步并发渲染只是 Texture 强大的一半另一半是智能预加载intelligent preloading详见 docs/_docs/intelligent-preloading.md。每个 node 都有“当前界面状态interface state”的概念该状态由一个ASRangeController持续更新——所有 node 容器都会在内部创建并维护各自的 range controller。脱离容器的 node 不会有任何 range controller 更新其状态这就会导致文章前面提到的上屏时“渲染闪烁”问题。7.1 三种核心界面状态区间当 node 被加入滚动或分页界面时它通常处于以下区间之一滚动时界面状态会随位置变化而更新界面状态说明Preload预加载离可见区最远的区间。在此从外部数据源API 或本地磁盘获取内容Display显示执行文本光栅化、图片解码等显示任务Visible可见node 至少有一像素在屏幕上区间分布示意参见 intelligent-preloading-ranges-with-names.png。这一模型在源码中有精确对应ASInterfaceState是定义于 Source/ASDisplayNodeInterfaceState.h 的位掩码枚举除上述三个状态外还包含ASInterfaceStateMeasureLayout测量布局与ASInterfaceStateNone默认态表示节点近期不会被预测上屏不执行预加载以及ASInterfaceStateInHierarchy节点不在 cell 中但在 window 中。7.2 ASRangeTuningParameters按“屏数”调区间大小每个区间的大小以“屏幕数screenfuls”为单位度量见 intelligent-preloading-ranges-screenfuls.png。默认尺寸适合大多数场景你也可以通过在滚动 node 上设置对应 range type 的 tuning parameters 轻松微调。在滚动集合的示意图中用户向下滚动时leading 方向即将进入的方向的区间明显大于trailing 方向用户远离的方向一旦用户改变滚动方向leading 与 trailing 两侧会动态互换从而把内存占用维持在最优水平。因此你只需要定义两个方向的大小而无需自己响应滚动方向的切换。智能预加载同样支持多个维度水平 垂直同时生效。7.3 在 node 子类中响应状态回调滚动过程中node 会在各区间之间移动并相应地进行数据加载、渲染等动作。你的 node 子类可以通过实现对应回调方法轻松接入这套机制回调协议定义于 Source/ASDisplayNodeInterfaceState.h 的ASInterfaceStateDelegate所有回调保证在主线程执行Visible 区间- (void)didEnterVisibleState - (void)didExitVisibleStateDisplay 区间- (void)didEnterDisplayState - (void)didExitDisplayStatePreload 区间- (void)didEnterPreloadState - (void)didExitPreloadState实现这些方法时记得调用super以免破坏 Texture 内部的状态机逻辑。此外协议还提供了-interfaceStateDidChange:fromState:用于在任意位变化时统一监听例如在节点退出可见区时释放缓存数据。八、进阶开发特性与学习资源随着框架演进Texture 累积了大量能显著减少样板代码的进阶特性官方 README 将其概括为如果你曾经被 cell 复用 bug 折磨、曾尝试为分页或滚动式界面高性能地预加载数据或只是想让应用少丢几帧那么集成 Texture 都能从中受益。相关实现散见于Source/目录例如 cell 复用与数据源管理Source/Details/ASDataController.mm、Source/Details/ASDelegateProxy.mm、批量抓取Source/Details/ASBatchContext.h等。继续深入学习的资源仓库内均可直接访问官方入门指南docs/_docs/getting-started.md示例工程集合examples 与 examples_extra其中 ASDKgram 是官方推荐的渐进式接入示例API 参考文档docs/appledocHTML 形式的类/协议/分类索引版本演进与变更CHANGELOG.md、RELEASE.md、docs/_docs/adoption-guide-2-0-beta1.md九、获取帮助、贡献与许可获取帮助Texture 社区使用 Slack 进行实时调试与讨论若在集成中遇到问题也可以在仓库的 Issues 中反馈仓库根目录 CONTRIBUTING.md 说明了问题反馈与贡献流程。发布流程详见 RELEASE.md。许可协议Texture 采用 Apache 2.0 开源协议可免费使用协议全文见 LICENSE。十、总结何时选择 Texture一句话概括 Texture 的适用场景当你的 iOS 应用包含大量图片、文本与复杂布局且对滚动流畅度有较高要求时Texture 通过 Node 抽象、声明式布局引擎与智能预加载三件套把 UIKit 时代无法绕开的主线程瓶颈转化为可并行的后台工作。集成路径也很清晰——先通过 docs/_docs/installation.md 完成安装用容器ASTableNode/ASCollectionNode承载ASCellNode子类在layoutSpecThatFits:中声明布局再按需实现didEnter*State回调接管数据预取与渲染时机即可获得稳定的流畅体验。赞分享移动开发UI组件【免费下载链接】TextureSmooth asynchronous user interfaces for iOS apps.项目地址https://gitcode.com/gh_mirrors/te/Texture点击查看免费下载相关推荐TextureAsyncDisplayKit框架实战指南用 Node 构建丝滑流畅的 iOS 异步 UITextureAsyncDisplayKit框架实战指南用 Node 构建丝滑流畅的 iOS 异步 UI Texture 是一个构建在 UIKit 之上的移动开发UI组件Texture 入门指南基于 ASDisplayNode 与异步布局引擎构建 60fps 的 iOS 界面Texture 入门指南基于 ASDisplayNode 与异步布局引擎构建 60fps 的 iOS 界面 Texture原 AsyncDisplayKit移动开发UI组件AsyncDisplayKit与现代iOS开发Texture框架演进AsyncDisplayKit与现代iOS开发Texture框架演进 本文详细探讨了AsyncDisplayKit现Texture框架从起源到现代发展的完移动开发UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑