适用于iOS的AsyncDisplayKit里面有什么

以Pinterest为例,Pinterest主屏幕是一个ASCollectionNode,每个Pin是一个ASCellNode,其中包含ASNetworkImageNodes,ASTextNodes。 在屏幕上,Pinterest的Pin的生命周期将经历从初始到可见的状态:

  • 初始状态:ASCollectionNode在Pin节点上运行批量计算。 引脚节点从子节点获取布局规格,然后为其子视图计算布局。 结果为_calculatedDisplayNodeLayout ,其中包含所有节点的框架。
  • 预加载状态:引脚的网络图像节点触发后台线程延迟加载图像url,从而导致本地UIImage。
  • 显示状态:在此状态下,节点将先前状态中的图像绘制到CoreGraphic的位图中,从而得到已解码内容,该内容已准备好在主线程中可见。
  • 可见状态:几乎处于主线程中。 layoutSublayouts从初始状态获取_calculatedDisplayNodeLayout以便设置框架。 图像节点渲染解码内容。

如果节点在当前状态尚未完成时进入下一状态怎么办?

如果图像节点尚未下载图像而进入显示状态,它将显示占位符。 下载完成后,图像触发再次显示。

如果在尚未完成批计算的情况下收集节点进入“显示”状态,则它将在主线程中运行布局(仅在第一次出现时)。 它足够智能,可以先计算可见节点,然后显示/预加载节点。 还要记住,计算是在多线程concurrent中同时运行的。

异步意味着在后台线程中进行操作,因此为了释放主线程的工作量,Concurrently可以利用CPU多核来减少在主线程中可用的时间。

AsyncDisplayKit的布局

如果您熟悉CSS盒模型,则ASDK的布局是CSS布局(填充,位置:相对,..)和FlexBox的子集。

如果您熟悉UIStackView,则ASDK的ASStackLayoutSpec类似于UIStackView,可以扩展子视图,并支持flex-spacing和对齐方式。

如果您仍然不知道ASDK的布局如何,请查看快速入门,一些示例和FlexBox。

布局规格

布局系统包含定义如何在屏幕上布局视图的组件。 ASDK布局的组件包括:

  • ASStackLayoutSpec:ASDK布局的核心是堆栈规范。 堆栈规格沿其水平宽度或垂直高度散布其子视图。 与UIStackView不同的是,始终在开始时就吸引“重力”子视图,堆栈规范允许在中心,末端甚至相等的分布间距吸引“重力”子视图。
  • ASInsetLayoutSpec:类似于CSS填充样式,允许您在内部插入。
  • ASRatioLayoutSpec,ASRelativeLayoutSpec:虽然ASRatioLayoutSpec允许您按比例考虑-而不是固定的宽度-高度,但ASRelativeLayoutSpec允许您考虑相对位置-而不是绝对位置。
  • ASOverlayLayoutSpec:拉伸布局规格以覆盖另一个规格。
  • 还有其他一些布局规范

ASDK的布局将上述所有布局规格组合在一起,以定义屏幕的布局。

为什么这个? 自动版式仍然存在。

ASDK设计其布局系统时,目标之一是使其足够简单,不仅运行速度快,而且易于实现。

与AutoLayout相比,ASDK要求所有节点必须具有固有大小或显式设置其大小。 例如,ASImageNode需要显式设置.preferedSize

与AutoLayout相比,ASDK不允许您在具有父级以上父级的子节点之间定义约束。 例如,您不能说:“我不知道图像的尺寸,但要使其宽度等于其父级的宽度”。 而且也无法定义子节点之间的大小约束。

以上两个要求使布局计算更加简单。 ASLayoutSpec的calculateLayoutThatFits:方法只需要执行一次即可从子节点获取所有信息,然后计算最终帧,而无需关心父级的约束。

  //ASRatioLayoutSpec.mm 
  -(ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize 
{
...
//选择最接近所需比例的尺寸。
const auto &bestSize = ...;
  const ASSizeRange childRange =(bestSize == sizeOptions.end())吗?  constrainedSize:ASSizeRangeIntersect(constrainedSize,ASSizeRangeMake(* bestSize,* bestSize)); 
  const CGSize parentSize =(bestSize == sizeOptions.end())吗?  ASLayoutElementParentSizeUndefined:* bestSize; 
  ASLayout * sublayout = [ self .child layoutThatFits:childRange parentSize:parentSize]; 
  sublayout.position = CGPointZero; 
  返回 [ASLayout layoutWithLayoutElement: self size:sublayout.size sublayouts:@ [sublayout]]; 
  } 

另一个目标是使ASDK的布局功能强大到足以定义甚至复杂的布局并支持多分辨率。 仅使用ASStackLayoutSpec,ASOverlayLayoutSpec,ASCenterLayoutSpec,我们就可以定义布局,例如Pinterest。

为什么LayoutSpec只是一个“规范”?

为了在主线程之外运行布局系统,ASDK需要从视图中删除布局规范。 返回到AutoLayout,当您创建约束时,需要使用2个UIViews对其进行初始化。 由于UIViews属于主线程,因此无法根据主线程计算布局。

另一个好处是,您无需在中间创建“容器” UIView,而只需对齐,间隔,覆盖……信息视图即可。 还记得当您将某些UIViews分组到一个容器视图中然后将该容器视图居中显示在屏幕上时吗?

如果您不使用ASDK进行布局怎么办
–减少单元格内容中的UIViews数量。
–减少单元格内容中的深度视图层次。
–手动预先计算单元格的高度(请参见此处),标签的大小,图像的大小(在下载模型页面后),将其缓存在模型中,然后在heightForCellAtIndex:和layoutSubViews:中使用(不要使用AutoLayout)。
–使用ASDK是最后的选择。

其他UI处理作品

主线程 文本栅格化

ASDK团队付出了巨大的努力来构建自己的TextKit引擎。 TextKit引擎计算文本的框架并将其绘制到CoreGraphic位图中,然后返回主线程进行渲染。

如果您不使用ASDK,该怎么办:
您将所有TextKit文件夹从ASDK复制到您的项目=]]。 但要注意许可:v

CornerRadius详细信息
在Pinterest主屏幕中查看Pin的图像? 剪裁成4个角以显示该系列的白色背景。

  _photoNode.willDisplayNodeContentWithRenderingContext = ^(CGContextRef上下文){ 
  CGRect范围= CGContextGetClipBoundingBox(context); 
[[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:10] addClip];
  }; 

这种方法称为预合成的Alpha角。 缺点是:由于GPU的alpha混合以及集合内容的白色背景,因此引入的开销很小。

另一种方法是将集合的白色背景合成到图像中,称为预合成的不透明角。 ASDK通过在UIImage+ASConvenience.m生成4个叠加角的方法来支持它:

  +(UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius cornerColor :( 可为空的 UIColor *)cornerColor fillColor:(UIColor *)fillColor AS_WARN_UNUSED_RESULT; 
  _photoNode.willDisplayNodeContentWithRenderingContext = ^(CGContextRef上下文){ 
  CGRect范围= CGContextGetClipBoundingBox(context); 
  UIImage * overlay = [UIImage as_resizableRoundedImageWithCornerRadius:10 cornerColor:[UIColor whiteColor] fillColor:[UIColor clearColor]]; 
[overdrawInRect:bounds];
  [[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:10] addClip]; 
  }; 

ew,今天足够了。 让我们休息一下,吃点东西,看地精电影。

关于ASDK的本系列文章的第2部分中有什么内容?

在第2部分中,我将在以下内容中回顾ASDK:体系结构,模式,预加载,自动子节点管理。

阅读更多

如果您想学习如何使用ASDK,请查看raywenderlich.com上的两部分教程:
https://www.raywenderlich.com/124311/asyncdisplaykit-2-0-tutorial-getting-started

在UITableViews中完美平滑滚动
关于在iOS最常用的构建基块 medium.com中达到60 FPS的优化的故事 圆角倒角
关于圆角处理,许多开发人员都坚持使用CALayer的.cornerRadius属性。 不幸的是,这… asyncdisplaykit.org