Table of Contents
理解离线数据存储选项
建立iOS的稳健离线经验需要仔细选择本地存储技术. 正确选择取决于数据的复杂性,查询需要和同步要求. 核心数据提供全对象图管理系统,与iCloud同步进行反向、验证和整合. 理想的应用是具有复杂关系和中等数据量的应用软件. 用户数据交换系统 用户数据交换系统 设计良好,但并非为大型数据集设计。 SQLite SQLite 直接访问关系数据库,通常通过FMDB或GRDB 包机使用;它能很好地控制查询和性能;对于图像或文件等结构不合理的数据, File系统[F:]是适当的,许多小组将SQLite或核心数据与[FLT: 组合 组合数据合并 共享 。
离线数据管理关键战略
数据同步架构
离线 iOS 应用程序必须定义本地和远程状态的聚合方式。 一个流行的模式是本地第一数据模型 : 所有写入先到本地存储,然后在连接返回时被推向服务器。 这种方法确保应用程序无论网络状态如何都保持响应。 执行 更改跟踪[ 使用时间戳、序列号或版本向量来检测修改。 当同步、 将本地变化推向服务器、 牵引远程变化和合并两侧时。 避免同时同步所有数据, 用于大型数据集; 使用 pagized 或delta % 同步。 对于背景同步, 杠杆 [[FLT: 5] 和 [[[FLT: 6] BTAskScheduler [FLT: 7] , 获取更新而无需用户干预。 Apple ' s [[[FLT: 8]]] BGScheduler 文档[FLT: 9] 详细安排维护任务。
解决冲突战略
当本地和远程数据独立变化时, 就会出现冲突。 选择一个适合您的使用大小写的解析策略 :
- Last Write Wins(LWW): 接受该版本,并附最近的印章。简单但可以丢弃用户编辑。
- 与复制重写:[] 对于列表等命令的数据,使用操作转换或CRDT合并操作(插入,更新,删除).
- 手册冲突解决: 向用户提交两个版本,让他们决定。最好进行协作编辑或批判数据。
- Server Authority: 服务器总是在比较版本向量后获胜,当服务器数据是canonical时使用.
在本地计划中记录冲突元数据( 如 & quot; local version & quot; 和 & quot; server verserver & quot;) , 以便冲突处理者能够做出知情的决定。 测试冲突假想, 既可以连接又可以同时修改 。
智能缓存和数据访问
缓存会减少延迟和磁盘 I/O。 执行一个[ [FLT: 0]] 多位缓存 [[FLT: 1] : 经常访问对象的内存缓存 (NSCAche 或你自己的) , 以及一个长期存储的持久缓存 (核心数据或SQLite ) 。 对于网络响应, 请使用 UURLSACSE 所建的 内存 , 并配有适当的缓存政策 (例如, [[FLT: 0] ) 。 对于图像文件, 杠杆 内存 , 加上磁盘缓存(例如, Kingfisher 或SDWebImage ) 。 在设计缓存时, 定义一个驱离政策(LRU、TLTLTL, 或尺寸) , 以防止无限制的增长。 避免在不加密的情况下隐藏敏感数据。对于文件和 [ NSFLT:8]
排队用户 启动更改
当用户在下线时执行写操作时, 将动作排队到本地商店。 一个常见的方法是创建 [[FLT: 0]] 运行表 [[FLT: 1] , 记录操作类型、 终点、 有效载荷和时间戳。 程序一旦上网, 就会按顺序( 或有依赖性解析度) 重放这些操作。 要处理部分失败, 执行 [[FLT: 2] 的单词[FLT: 3] , 在每个操作中附加独特的 UUID 。 如果重播失败( 如冲突或服务器错误) , 标记操作在后期进行手动审查或重试。 Apple 的 [[FLT: 4] URL 装入系统[ [FLT: 5] 提供了用于重试逻辑的强力网络原始 。
在 iOS 中执行离线模式
检测连接性变化
使用 [[FLT: 0]] 网络框架 (NWPathMonitor) 或旧 可操作性 类来观察网络过渡. NWPathMinitor 提供了连接状态的响应流(Wi ⁇ Fi, 蜂窝, 或 eethnet) 。 订阅路径更新后, 并发布UI 层的通知。 例如 :
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
let isOnline = path.status == .satisfied
DispatchQueue.main.async {
NotificationCenter.default.post(name: .networkStatusChanged, object: isOnline)
}
}
monitor.start(queue: .global())
扩展此功能, 区分昂贵( 细胞) 和受限连接, 这样您就可以推迟大同步 。
正在无缝切换数据源
当连接下降时, app应该透明地从远程API调用到本地存储. 执行一个 [[FLT: 0]] 数据源抽象层 [[[FLT: 1]]] : 定义一个协议(例如 [[FLT: 2]]] , 方法有 [[FLT: 3]]], [[FLT: 4]] 和 [[FLT: 5]]] 。 提供两个执行: [[[FLT: 6] 和 [[FLT: 7]] 。 一个协调员类根据当前网络状态决定使用哪个提供者。 这个模式将 UI连接到一个单一接口, 避免在视图控制器中进行挤压。 对于实时的听众, 将本地通知与远程推送通知合并, 以保持一致性 。
用户反馈和透明度
当用户下线时通知用户, 并如何存储其动作。 使用 [[ FLT: 0]] 海关导航条或横幅 [[ FLT: 1] 来显示下线状态( 如 & quot; 您下线了 。 变化会在连接时同步 。 在背景同步时显示 [ [ [ FLT: 2] ] 同步指标 [ [ [ FLT: 3]] (spinning got, 进步 bar) 。 当排队时, 显示同步图标上的徽章, 或提供专用 & quot; Pending 更改 & Quot; 屏幕, 用户可以在此审查和取消排队操作 。 对于上传, 显示每个项目的进展, 如果数据是大( 类似照片 ) 。 总是提供一种方式, 强制同步 [ [ [ [ FLT: 4] ] 手动( e.g. , pull {to>rerefree) 用户可以控制。 避免分散提醒 - 使用非阻断 模式 。
测试和调试离线假想
测试离线行为至关重要, 但往往被忽视。 使用 Xcode 的 [[ FLT: 0]]] 网络链接条件( 通过硬件 IO 工具提供) 模拟网络条件。 为 :
- 写入操作中出现连接缺失 。
- 多个同步队列活动时重联 。
- 冲突, 有两个设备将同一记录修改为离线 。
- 大型数据同步通过缓慢或间断的连接.
- 应用终止 中 同步。
添加网络状态转换、 同步队列冲洗和冲突解决的日志。 使用自定义子系统来捕捉这些生产中的事件, 用于调试用户的“ 已报告的问题 ” 。 单位通过注射模拟离线/ 在线状态的模拟提供者来测试您的数据提供者抽象。 对于集成测试, 请使用专用的测试环境, 从而可以程序化地通过代理设备来切换网络可达性, 如 [ [ [ [FLT: 2]]] Chales [ [[FLT: 4]] 或 [[FLT: 4] 网络链接连接条件 [[FLT: 5]]。 最后, 运行 [[FLT: 6] XCTest [FLT: 7] UI测试, 重复切换Airplane Mode, 并同时进行用户流量来揭开种族条件 。
结论
构建iOS的弹性离线体验需要围绕存储,同步,冲突处理和用户通信进行深思熟虑的架构决策. 借助核心数据或SQLite对结构化数据进行杠杆化的利用,实施数据源抽象反应连接变化,排队用户行动进行后同步,您创建了一个没有互联网连接的应用程序,仍然可以完全运行. 优先使用冲突解决策略,保持数据完整性,让用户随时了解同步状态. 以现实网络条件进行彻底测试,将及早发现边缘案例. 执行良好时,离线第一方法不仅会提高用户满意度,而且会减少服务器负荷和网络依赖性. 为进一步阅读,探索苹果的 货币编程指南[ ,以及 URL 高级网络技术文件。 将离线作为第一 特性,您的用户将以忠诚和参与方式感谢您.