HeckelDiff
Pure Swift 实现了 Paul Heckel 的 文件间差异隔离技术
特性
这是一个简单的差分算法,它提供了将一个集合转换为另一个集合所需的最小步骤集。转换被列为离散操作
- 插入 - 应该插入哪些项以及它们的索引。
- 删除 - 应该从数组中删除哪些项以及它们的索引。
- 移动 - 应该移动哪些项以及它们的起点和终点索引。
- 更新 - 应该更新哪些项(以新上下文替换)以及它们的索引。
这些操作在 线性 时间内计算,使用了 这篇论文 中描述的算法。
了解这组操作对于有效地更新 UITableViews 和 UICollectionViews 特别有帮助。
示例
考虑一个比较整数列表的简单示例
let o = [1, 2, 3, 3, 4]
let n = [2, 3, 1, 3, 4]
let result = diff(o, n)
// [.move(1, 0), .move(2, 1), .move(0, 2)]
let o = [0, 1, 2, 3, 4, 5, 6, 7, 8]
let n = [0, 2, 3, 4, 7, 6, 9, 5, 10]
let result = diff(o, n)
// [.delete(1), .delete(8), .move(7, 4), .insert(6), .move(5, 7), .insert(8)]
orderedDiff
也可用,它提供了一组 UIKit 环境中批处理更新友好的操作(注意如何将 move
替换为 insert
和 delete
的成对操作)
let o = [1, 2, 3, 3, 4]
let n = [2, 3, 1, 3, 4]
let result = orderedDiff(o, n)
// [.delete(2), .delete(1), .delete(0), .insert(0), .insert(1), .insert(2)]
UITableView/UICollectionView支持
HeckelDiff内置了对生成高效的批量更新UITableView
和UICollectionView
的支持。在这两个类上都提供了方法,允许告知相应的表或集合视图其数据模型已更改。
例如
tableView.applyDiff(previousItems, newItems, withAnimation: .fade)
或
collectionView.applyDiff(previousItems, newItems)
更新支持
传递给diff
的集合中的元素必须符合Hashable
协议。HeckelDiff使用元素的hashValues
来确定它们是应该被插入、删除还是移动。在某些情况下,元素会被标记为需要更新。这是因为尽管两个元素的hashValues
可能相同,但它们可能并不相等。您可以通过以这种方式实现Hashable
协议来利用这一点,使得元素在适当的时候得到更新。
例如,您可能有两条记录都指向同一个人(也许您使用记录ID作为哈希值)。您可能想要支持个人电话号码可能更改的情况,但记录本身在数组中的位置保持不变。您的Equatable
实现可能会考虑电话号码值,而您的hashValue
可能只反映底层的记录ID值。
在UITableView
或UICollectionView
的上下文中,您可以通过重新加载需要更新的指定行来最有效地处理这种情况(而不是删除它然后重新插入)。使用提供的applyDiff
函数让HeckelDiff为您执行此操作。
安装
Carthage
您可以使用以下命令用Homebrew安装Carthage
$ brew update
$ brew install carthage
将以下行添加到您的Cartfile
github "mcudich/HeckelDiff"
运行carthage update
,然后确保将HeckelDiff.framework
添加到"Linked Frameworks and Libraries"和"copy-frameworks"构建阶段。
CocoaPods
CocoaPods 是 Cocoa 项目的依赖管理器。您可以使用以下命令安装它
$ gem install cocoapods
要使用 CocoaPods 将 TemplateKit 集成到您的 Xcode 项目中,请在您的 Podfile
中指定它
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'HeckelDiff', '~> 0.1.0'
end
然后,运行以下命令
$ pod install
要求
- iOS 9.0+
- Xcode 8.0+
- Swift 3.0+