当 tableView 或 collectionView 的数据发生变化时,我们需要自己来处理控制器的刷新行为,比如reloadData insertRowsAtIndexPatch 等刷新方法。我们很可能会使用到枚举或if else进行逻辑判断。在阅读 Yep 代码的时候发现了一种利用 extension 的方法,可以让控制器中的代码更加简洁。

我们首先为 UITableView 创建一个 extension, 并创建一个 enum 用来表示 tableView 的所有刷新行为。

1
2
3
4
5
6
7
8
9
10
11
extension UITableView {
enum WayToUpdata {
case none
case reloadData
case insert([IndexPath])
case reloadAtIndexPath([IndexPath])
}
}

我们定义的 WayToUpdate 中有两个 case 关联了 IndexPath 的数组。 其关联的对象就是我们要刷新的 indexPaths。

接着为刚才声明的 enum 添加一个控制更新行为的方法:performWithTableView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func performWithTableView(tableView: UITableView) {
switch self {
case .none:
printLog("tableView WayToUpdata: None")
case .reloadData:
printLog("tableView WayToUpdata: ReloadData")
tableView.reloadData()
case .reloadAtIndexPath(let indexPaths):
printLog("tableView WayToUpdata: ReloadAtIndexPath")
tableView.reloadRows(at: indexPaths, with: .none)
case .insert(let indexPaths):
printLog("tableView WayToUpdata: Insert")
tableView.insertRows(at: indexPaths, with: .none)
}
}
}

上面的代码是枚举某个 wayToUpdate 实例,来确定要进行的 reloadDate 行为。

tableView 的 extension 部分完成后,我们来看在 tableViewController 中的应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 加载新数据后更新 UI 的闭包
let completion: ([Feed]) -> Void = { feeds in
DispatchQueue.main.async { [weak self] in
guard let strongSelf = self else {
return
}
let newFeeds = feeds
// 定义一个可变的更新行为.
var wayToUpdata = UITableView.WayToUpdata.none
if strongSelf.feeds.isEmpty {
wayToUpdata = .reloadData
}
switch uploadMode {
// 顶部插入新数据时
case .top:
// 使用reloadData的方法.
wayToUpdata = .reloadData
strongSelf.feeds = newFeeds
// 底部加载更多数据时
case .loadMore:
let oldFeedsCount = strongSelf.feeds.count
let oldFeedIDs = Set<String>(strongSelf.feeds.map
{ $0.objectId })
var newRealFeeds = [Feed]()
for feed in newFeeds {
if !oldFeedIDs.contains(feed.objectId) {
newRealFeeds.append(feed)
}
}
strongSelf.feeds += newRealFeeds
let newFeedCount = strongSelf.feeds.count
let indexPaths = Array(oldFeedsCount..<newFeedCount).map {
IndexPath(row: $0, section: Section.Feed.rawValue)
}
// 使用插入的方式,并关联需要插入的 indexPaths
wayToUpdata = .insert(indexPaths )
}
// 最后指定需要更新的 tableView
wayToUpdata.performWithTableView(tableView: strongSelf.tableView)
finish?()
}
}

OK! Done.
以后凡是有 tableView 需要 reloadData, 就都可以使用这样的方式.