拓冰建站拓冰建站
首页 / 资讯中心 / 正文

FMMosaicLayout性能优化解读:布局属性缓存与可见区域查询机制

FMMosaicLayout性能优化解读布局属性缓存与可见区域查询机制【免费下载链接】FMMosaicLayoutA drop-in mosaic collection view layout with a focus on simple customizations.项目地址: https://gitcode.com/gh_mirrors/fm/FMMosaicLayoutFMMosaicLayout 是一个面向 iOSUICollectionView的轻量级马赛克瀑布流布局组件只需即插即用即可把图片内容排成错落有致的马赛克墙。当页面承载成百上千个图片 Cell 时布局性能往往决定了滚动手感是否流畅。本文带你解读 FMMosaicLayout 背后的两大核心性能设计——布局属性缓存与可见区域查询看看一个只有几百行的布局类是如何做到平滑滚动的。FMMosaicLayout 瀑布流布局原理速览 FMMosaicLayout 继承自UICollectionViewLayout把内容区按列切分默认 2 列每来一个 Cell 就放入当前最矮的列从而让整体视觉高度始终均衡——这正是 Facebook 图片墙的经典算法思路。列高追踪内部用columnHeightsPerSection二维数组记录每个 section 中每一列的累计高度配合找最矮列/最高列的小工具方法完成定位两种 Cell 尺寸大号占一整列与小号两个并排占一列由代理方法在布局时逐格决定示例工程Example/FMMosaicLayout/FMMosaicCollectionViewController.m中用 3 个 section、共 220 张示例图如Example/FMMosaicLayout/Images.xcassets/下的素材验证了这套机制。优化一布局属性缓存——一次算完取用即查 ⚡这是 FMMosaicLayout 最核心的性能设计源码见 Pod/Classes/FMMosaicLayout.m。在 prepareLayout 中批量完成全部计算当prepareLayout被调用时布局类会一次性遍历所有 section 和所有 Cell算出每个单元格的 frame 后立刻写入缓存字典cellLayoutAttributes以indexPath为键表头、表头等补充视图同样写入supplementaryLayoutAttributes。// 缓存结构Pod/Classes/FMMosaicLayout.m 第 44、49 行 property (nonatomic, strong) NSMutableDictionary *cellLayoutAttributes; property (nonatomic, strong) NSMutableDictionary *supplementaryLayoutAttributes;之后的查询变成 O(1) 字典查找缓存建好之后系统询问某个 Cell 的位置时只需一句字典取值- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.cellLayoutAttributes objectForKey:indexPath]; }没有任何现场计算滚动过程中反复查询也不会产生额外开销。懒加载 统一重置控制内存与算力三个缓存属性列高、Cell 属性、补充视图属性都采用懒加载 getter——真正用到时才创建避免无谓初始化而当布局确实需要重算时resetLayoutState会一次性清空所有缓存第 193-202 行保证新旧数据不混杂。优化二可见区域查询——只渲染屏幕上的内容 layoutAttributesForElementsInRect:是驱动UICollectionView滚动的关键钩子每次滚动集合视图会把一块可见区域传进来问这里需要画哪些元素FMMosaicLayout 的回答是——从缓存里做交集过滤遍历已缓存的 Cell 属性与补充视图属性用CGRectIntersectsRect判断 frame 是否与可见区域相交只返回相交的那一小部分。- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { // 仅返回与 rect 相交的已缓存布局属性不做任何现场计算 if (CGRectIntersectsRect(rect, attributes.frame)) { [attributesInRect addObject:attributes]; } ... }这意味着即使示例工程里有 220 张图片屏幕一次只认领几十个 Cell 的属性对象其余内容完全不参与渲染管线——这是滚动流畅的直接原因。优化三精准的布局失效——旋转才算滚动不算 重算布局是昂贵操作所以什么时候该重算必须精打细算。FMMosaicLayout 在shouldInvalidateLayoutForBoundsChange:第 182-191 行中的策略非常克制场景是否重算布局原因上下/左右滚动offset 变化❌ 否尺寸未变缓存继续有效设备旋转、分屏尺寸变化✅ 是列宽改变所有 frame 必须重排只有 bounds 的size发生变化时才调用prepareLayout清空缓存并重新走一遍完整计算流程纯滚动则复用现有缓存零重算开销。写自定义布局时可借鉴的 5 个性能经验 从 FMMosaicLayout完整实现约 450 行见 Pod/Classes/FMMosaicLayout.m可以提炼出通用的自定义布局性能清单批量计算 字典缓存在prepareLayout中一次算完所有 frame后续查询一律纯查表用 indexPath 作字典键定位任意 Cell 属性 O(1) 完成无需遍历数组可见区域查询只做过滤layoutAttributesForElementsInRect:内不计算、只筛选把计算前置到缓存阶段区分失效时机严格区分尺寸变化与滚动偏移只在必要时清空缓存重算代理回调保持轻量列数、Cell 尺寸等代理方法在prepareLayout阶段逐个 Cell 调用参考FMMosaicLayout.h中的FMMosaicLayoutDelegate不要在回调里做耗时操作。总结FMMosaicLayout 的性能秘诀可以浓缩为三个词缓存、过滤、精准失效。它在布局阶段一次性算好全部属性并缓存滚动阶段只对可见区域做相交过滤并且仅在尺寸真正变化时才重算——这套把昂贵计算前置、把高频查询变便宜的思路是任何自定义UICollectionViewLayout都值得借鉴的实战经验。✨【免费下载链接】FMMosaicLayoutA drop-in mosaic collection view layout with a focus on simple customizations.项目地址: https://gitcode.com/gh_mirrors/fm/FMMosaicLayout创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门