ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Core Data与CollectionView UI实时同步:CompositionalDiffablePlayground Jokes示例收藏、上下文菜单与骨架屏动画完整实现

2026/8/23 11:55:51 拓冰建站 浏览量
Core Data与CollectionView UI实时同步:CompositionalDiffablePlayground Jokes示例收藏、上下文菜单与骨架屏动画完整实现 Core Data与CollectionView UI实时同步CompositionalDiffablePlayground Jokes示例收藏、上下文菜单与骨架屏动画完整实现【免费下载链接】CompositionalDiffablePlayground.iosExamples showing Compositional Layout, Diffable Data Sources and more!项目地址: https://gitcode.com/gh_mirrors/co/CompositionalDiffablePlayground.iosCompositionalDiffablePlayground.ios 是一个专门演练 iOS 现代 CollectionView API 的示例工程核心演示 Compositional Layout组合式布局与 Diffable Data Source可差分数据源。本文以其中功能最完整的Jokes笑话列表示例为主线拆解Core Data 与 CollectionView UI 实时同步的完整机制涵盖收藏持久化、长按上下文菜单朗读/取消收藏与骨架屏闪烁动画的实现思路帮助新手理解 Diffable、Compositional 与 Core Data 三者在真实项目中如何协作。项目概览现代 CollectionView API 的练习场 主界面 ViewController.swift 本身也是一个由 Diffable 驱动的 CollectionView菜单分为两区Layout 基础示例列表、简单网格、懒加载网格、吸顶头部、响应式布局、Onboarding 流程等 8 种纯布局玩法复杂实战示例Jokes 笑话列表、Apple Photos 风格画廊见下方项目自带示例图片、Instagram 风格个人主页、Indie App 新闻流等。其中 Jokes 示例是唯一同时串联了网络加载 Core Data 收藏 上下文菜单 语音朗读 骨架屏的完整场景因此值得单独拆解。Core Data 与 CollectionView UI 如何保持实时同步整个同步链路只由四个角色完成核心思想是UI 永远只由 snapshot 驱动而 snapshot 又永远只从 Core Data 和网络的最新结果构建。角色文件职责数据库单例Database.swift持有NSPersistentContainer暴露viewContext封装saveContext()数据模型Joke.swiftJoke: NSManagedObject字段为 id、setup、punchline、created实体定义contents可视化数据模型中的Joke实体同步桥JokesViewController.swift用NSFetchedResultsController监听数据库变化关键在 JokesViewController.swift 末尾这个只有两行的 delegatefunc controller(_ controller: NSFetchedResultsControllerNSFetchRequestResult, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) { datasource.apply(self.snapshot(), animatingDifferences: true) }只要 Core Data 中Joke记录发生增、删、改NSFetchedResultsController就会回调它而apply(_:animatingDifferences:)会自动对比新旧快照只重绘变化的行并附带原生插入/移除动画。收藏或删除一条记录UI 在同一个 runloop 内自动刷新——这就是“实时同步”的全部秘密。一键收藏快照驱动的 UI 更新 ⭐收藏入口在 JokesViewController.swift 的两个方法中favoriteJoke(_:)先用Joke.byIdFetchRequest(id:)查询是否已存在防止重复收藏再新建Joke对象写入并saveContext()unfavoriteJoke(withId:)按 id 取出记录后context.delete(_:)同样触发保存。而snapshot()方法每次都直接从fetchedResultsController.fetchedObjects读取最新的收藏列表构建出favoriteJokes(count:state:)分节——节标题显示Favorites (n)并可通过ActionButtonHeader按钮整体展开/折叠。两个细节值得注意Joke.Diffable的hash(into:)只合并id见 Joke.swift保证 Diffable 算法能正确识别“同一条笑话”内容变化不会误判为增删JokeCell.swift 根据数据来源切换星形图标来自网络的显示空心星可收藏来自 Core Data 的显示实心星已收藏一眼区分两种状态。长按上下文菜单把笑话读出来 ️长按菜单由 JokesViewController.swift 的contextMenuConfigurationForItemAt实现逻辑简洁先通过datasource.itemIdentifier(for:)反查当前 item骨架屏占位项.loading直接返回 nil 不显示菜单固定提供Hear动作用AVSpeechSynthesizer朗读setup punchline仅当 item 属于收藏分节时额外追加Unfavorite动作调用前面提到的删除逻辑。由于删除会走 Core Data 保存 → FRC 回调 →apply(snapshot)的全链路菜单里的“取消收藏”同样享受自动 diff 动画无需手写任何刷新代码。![CollectionView 骨架屏加载示例的项目内置头像示例图](https://raw.gitcode.com/gh_mirrors/co/CompositionalDiffablePlayground.ios/raw/7bbc7612548ffe6d8b11906fdf376ccdd0987153/CompositionalDiffablePlayground/CompositionalDiffablePlayground/Assets.xcassets/mockAvatar.imageset/Screenshot 2021-01-16 at 14.25.55.png?utm_sourcegitcode_repo_files)骨架屏闪烁动画20 行代码做出 shimmer 效果 ⚡数据未返回时snapshot()会向.jokes分节填入 8 个Item.loading(UUID)占位项每个 UUID 独立避免复用同一身份cell 分支中调用showLoading()见 JokeCell.swift创建一个CAGradientLayer颜色为透明 → 10% 黑色 → 透明宽度放大 3 倍并左移作为“光带”用CABasicAnimation动画locations属性从[0.0, 0.1, 0.2]到[0.8, 0.9, 1.0]duration 1.1、repeatCount .infinity得到循环扫过的 shimmer 效果在prepareForReuse()中执行shimmerLayer?.removeFromSuperlayer()防止 cell 复用时残留动画。这套“占位 item 渐变光带动画 复用时清理”的组合可以直接迁移到任何 Diffable 列表。关键文件路径速查表功能模块文件路径笑话列表控制器快照/FRC 同步/上下文菜单ViewControllers/JokesViewController.swift骨架屏 shimmer 动画单元格Views/JokeCell.swift网络笑话 DTOModel/DTO/JokeDTO.swift共享协议setup/punchlineProtocols/JokeProtocol.swiftCore Data 实体与排序请求Database/Joke.swift持久层单例Database/Database.swift实体模型文件Database.xcdatamodel/contents网络请求official-joke-apiNetworking/SimpleNetworkHelper.swift通用排序请求扩展Database/Managed.swift获取项目并运行 执行以下命令克隆仓库用 Xcode 打开工程选择 iOS 13 模拟器运行即可Jokes 需要网络访问笑话 APIgit clone https://gitcode.com/gh_mirrors/co/CompositionalDiffablePlayground.ios运行后在主页第二个分节点击Jokes list即可体验完整效果进入时先看到 8 格 shimmer 骨架屏加载完成后逐行动画填充点星形收藏会实时出现在顶部 Favorites 分节长按任意一条笑话可朗读或取消收藏。对照文中四个核心文件阅读源码是掌握Core Data 与 CollectionView 实时同步的最佳路径。【免费下载链接】CompositionalDiffablePlayground.iosExamples showing Compositional Layout, Diffable Data Sources and more!项目地址: https://gitcode.com/gh_mirrors/co/CompositionalDiffablePlayground.ios创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考