简介

FlexibleDiff 是一个简单的 Swift 集合差异比较 μ框架,允许为差异比较定义分离的标识 (identity) 和相等性 (equality)。

对于一般的业务场景,两个实例的完全不等并不一定意味着标识上的不等 —— 如果两个实例的标识相同,则仅仅意味着它们所包含的数据发生了变化。 然而,由于大多数差异比较 μ框架仅依赖于 —— 并且因此受限于 —— Equatable 协议,它们无法表达标识相同但数据不同的场景,这种场景在交互式应用程序中尤其常见。

FlexibleDiff 通过支持使用自定义的相等性标识定义来计算变更集来解决这个问题。

例如,给定以下定义:

let previous: [Book]
let current: [Book]

struct Book: Equatable {
    let isbn: String
    var name: String
    var publishedOn: [Date]
}

我们可以提供自定义的标识定义,并了解到 ISBN 相同的书籍发生的就地更改 (in-place mutated books) ,或 ISBN 相同的书籍在不同位置发生了更改。

let changeset = Changeset(previous: previous,
                          current: current,
                          identifier: { book in book.isbn },
                          areEqual: Book.==)

与传统的基于 Equatable 的 μ框架相比,改进的差异比较表达能力允许发出更合适的集合视图动画。

除了灵活的 API,FlexibleDiff 还为常见用例提供了一些便利:

Collection.Element (集合元素) Identified By (通过...标识) Compared By (通过...比较)
AnyObject 对象标识 对象标识
AnyObject & Equatable 对象标识 对象标识或值相等。
AnyObject & Hashable 对象标识或值相等。 对象标识或值相等。
Hashable 值相等 值相等

开始使用

FlexibleDiff 以独立的 Xcode 项目提供,并支持 Carthage 和 CocoaPods。

# Carthage
github "RACCommunity/FlexibleDiff"

# CocoaPods
pod "FlexibleDiff"

示例应用程序

Xcode workspace 包含一个使用 FlexibleDiff 的示例应用程序。 请务必运行 git submodule update --init 以在 Xcode 中构建应用程序目标之前获取依赖项。

关于算法的说明

该实现是从 Paul Heckel 提出的流行的 O(n) 差异算法演变而来,该算法在他的 1978 年的论文“用于隔离文件之间差异的技术” 中进行了描述。 该算法是多个平台上许多框架的基础,包括但不限于 IGListKit

许可证

在 MIT 许可证下获得许可。