ArrayUpdater
概述
ArrayUpdater 是一个用于计算从一组数组到另一组数组所需插入、删除和重载的框架。其主要用途是在呈现的数据发生变化时简化更新表格和集合视图的过程。该框架返回一个包含所需插入、删除和重载的结构体,以及将它们映射到索引的便利函数。随后,这些索引可以直接用于开始/结束更新调用(表格视图)或performBatchUpdates调用(集合视图)。
使用方法
协议要求
代码
struct Park: Updatable {
let id: String
let name: String
}
说明
为了让ArrayUpdater计算插入和删除,类型必须遵守Equatable
协议。然而,框架还需要某种方法来知道对象或值在意义上更新了,即使它们相等(重新加载)。
针对此,ArrayUpdater提供了扩展Hashable
(它反过来扩展了Equatable
)的Updatable
协议。Updatable
有一个要求,即类型必须有id
属性。遵守的类型将实现Equatable
,框架将使用相等检查和id
属性来确定数组中哪些项需要就地更新。
更新数组
代码
let arches = Park(id: "NPS01", name: "Arches")
let grandCanyon = Park(id: "NPS02", name: "Grand Canyon")
let greatSmoky = Park(id: "NPS03", name: "Great Smoky Mountains")
let greatSmoky2 = Park(id: "NPS03", name: "Great Smokies")
let yosemite = Park(id: "NPS04", name: "Yosemite")
let zion = Park(id: "NPS05", name: "Zion")
let parks1 = [arches, greatSmoky, yosemite, zion]
let parks2 = [zion, grandCanyon, greatSmoky2, yosemite, arches]
let update = parks1.update(to: parks2)
print(update)
输出
▿ Update
▿ reloads : 1 element
- 0 : 1
▿ deletions : 2 elements
- 0 : 0
- 1 : 3
▿ insertions : 3 elements
- 0 : 0
- 1 : 1
- 2 : 4
说明
表格和集合视图按特定顺序执行更新,在插入之前先发生重载和删除。因此,在上面的例子中,让我们从第一个数组开始,看看我们是怎样得到第二个数组的。
- 我们在索引1处进行了一次重载。"greatSmoky"和"greatSmoky2"因为它们的id相等而被认为是相等的,但它们的名称不匹配,因此该项需要重载。由于重载和删除发生在插入之前,所以这次重载是在其索引1处执行的,这在第一个数组中。
- 我们有两个删除操作,分别在索引0和3处。同样,删除操作发生在插入之前。在我们的例子中,"arches"和"zion"已改变位置,因此需要在被重新插入到新位置之前被删除。
- 此时我们的数组是
[greatSmoky2, yosemite]
。为了得到parks2
,我们需要在索引0、1和4处分别插入"zion"、"grandCanyon"和"arches"。
有关更多信息,请参阅Apple文档中的“操作顺序和索引路径”部分
表格 & 集合视图
代码
parks = parks1
let update = parks1.update(to: parks2)
parks = parks2
let reloads = update.reloads.indexPaths(inSection: 0)
let deletions = update.deletions.indexPaths(inSection: 0)
let insertions = update.insertions.indexPaths(inSection: 0)
// Table View
tableView.beginUpdates()
tableView.reloadRows(at: reloads, with: .automatic)
tableView.deleteRows(at: deletions, with: .automatic)
tableView.insertRows(at: insertions, with: .automatic)
tableView.endUpdates()
// Collection View
collectionView.performBatchUpdates({
self.collectionView.reloadItems(at: reloads)
self.collectionView.deleteItems(at: deletions)
self.collectionView.insertItems(at: insertions)
}, completion: nil)
说明
变量parks
代表我们的数据源,最初设置为原始数据parks1
。ArrayUpdater计算出更新,然后在表格或集合视图更新开始之前,将parks
设置为parks2
,以确保数据源已更新。
ArrayUpdater提供了一个便利函数,用于将Int数组(重载、删除或插入索引)转换为索引路径。它包括一个段落参数,以支持具有多个段的数据源。在这里,数据源只有一个段落,因此更新索引将转换为第0个段中的相关索引路径。
示例数据源
代码
class ParksTableViewDataSource: NSObject, UITableViewDataSource {
private(set) var parks: [Park]
init(parks: [Park]) {
self.parks = parks
}
func update(with parks: [Park]) -> IndexUpdate {
let update = self.parks.update(to: parks)
self.parks = parks
return update
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return parks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ParkCell")!
let park = parks[indexPath.row]
cell.textLabel?.text = park.name
return cell
}
}
说明
以上是使用 ArrayUpdater 实现表格视图数据源的示例。关键部分是“update:with”函数,它返回一个包含所需重新加载、删除和插入的 IndexUpdate
值。该函数简单地计算更新,替换底层数据,并返回 IndexUpdate
值。然后表格视图可以根据 表格与集合视图 中描述的方式对更新进行动画处理。
安装
注意: ArrayUpdater 需要 Swift 3(以及greater)(>)或更高版本。
使用 ArrayUpdater 的目标必须支持嵌入式 Swift 框架。
Swift 包管理器
Swift 包管理器 是 Apple 为 Swift 框架提供的官方包管理器。要使用 Swift 包管理器进行安装
-
将 ArrayUpdater 添加到您的 Package.swift 文件
import PackageDescription let package = Package( name: "MyAppTarget", dependencies: [ .Package(url: "https://github.com/toddkramer/ArrayUpdater", majorVersion: 1, minor: 3) ] )
-
运行
swift build
。 -
生成 Xcode 项目
swift package generate-xcodeproj
Carthage
Carthage 是 Cocoa 项目的去中心化依赖管理器。要用 Carthage 安装 ArrayUpdater
-
请确保已安装 Carthage。安装 Carthage。
-
将 ArrayUpdater 添加到您的 Cartfile
github "toddkramer/ArrayUpdater" ~> 1.3.0
-
运行
carthage update
并 添加适当的框架。
CocoaPods
CocoaPods 是 Cocoa 项目的集中式依赖管理器。要用 CocoaPods 安装 ArrayUpdater
-
请确保已安装最新版本的CocoaPods。查看安装指南。
-
将ArrayUpdater添加到您的Podfile中。
use_frameworks! pod 'ArrayUpdater', '~> 1.3.0'
-
运行
pod install
。