(在与下面的@AndreasOetjen 讨论后重写了这个问题。感谢他的评论。)
我在使用UITableViewdiffable 数据源时遇到了问题。在我的应用程序中,当用户修改一个项目时,它可能会更改同一表视图中显示的另一个项目。问题是,在我创建并应用包含两个项目的新值的新快照后,间接更改的项目的 UI 没有更新。
起初我认为 diffable 数据源能够检测不同快照中项目的值变化。例如,它可能以这种方式工作:如果它发现两个快照包含相同的项目(即,两个快照中的项目具有相同的哈希值),则比较它们的值并在值更改时更新表视图中该项目的行。但是,后来我意识到它可能不会那样工作,因为 diffable 数据源没有定义任何 API 来获取和比较项目值(我最初的想法是它使用了description计算属性和==操作,但现在我认为这不是真的)。
所以我目前的理解是 diffable 数据源使用项目的散列来检测项目顺序变化(即插入新项目,旧项目仍然存在等),而不是项目值变化(即旧项目仍然存在但其值已更改)。如果这种理解是正确的,那么就引出了这个问题:如何使用diffable数据源来实现以下场景?
在旧UITableViewAPI 中,这可以通过调用reloadRows()或来实现reloadData()。但是如何使用 diffable 数据源来做到这一点?
更新:
在花时间做实验并解决问题后,我认为上述问题的理解是错误的。请看我下面的回答。我相信这解释了 diffable 数据源的工作原理。我希望它对其他有同样困惑的人有所帮助。我很高兴被证明是错误的。真的。因此,如果您有不同的想法,请留下您的答案。
一个部分可能包含 1 个页眉、许多内容项和 1 个页脚。
对于DiffableDataSource,网上的大部分例子,都是enum用来表示Section的。例如
func applySnapshot(_ animatingDifferences: Bool) {
var snapshot = Snapshot()
snapshot.appendSections([.MainAsEnum])
snapshot.appendItems(filteredTabInfos, toSection: .MainAsEnum)
dataSource?.apply(snapshot, animatingDifferences: animatingDifferences)
}
Run Code Online (Sandbox Code Playgroud)
但是,当 Section 有动态内容页脚时,我们可能需要使用 struct 来表示 Section。例如
import Foundation
struct TabInfoSection {
// Do not include content items [TabInfo] as member of Section. If not, any mutable
// operation performed on content items, will misguide Diff framework to throw
// away entire current Section, and replace it with new Section. This causes
// flickering …Run Code Online (Sandbox Code Playgroud) 我正在更新,UITableViewController以使用新的UITableViewDiffableDataSource,但所有工作都正常,但要滑动删除即可。
这是我如何使用滑动删除的示例
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let lockedAction = UIContextualAction(style: .normal, title: "TEST") { (_, _, completion) in
print("tapped....")
completion(true)
}
return UISwipeActionsConfiguration(actions: [lockedAction])
}
Run Code Online (Sandbox Code Playgroud)
但这在UITableViewController具有UITableViewDiffableDataSource
没有滑动,方法中的断点也不会被调用
我以为这是一个Beta错误,但是我更新到了Xcode 11 GM,并且发生了同样的事情。
感谢您的任何建议
我正在修修补补,UITableViewDiffableDataSource并且能够毫无问题地加载 tableView。我正在尝试在 tableView 中创建节标题,但是我遇到了一些奇怪的行为。
节 enum enum 定义如下:
enum AlertLevel: String, Codable, CaseIterable {
case green = "green"
case yellow = "yellow"
case orange = "orange"
case red = "red"
}
Run Code Online (Sandbox Code Playgroud)
这是我的实现 tableView(viewForHeaderInSection:)
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let label = UILabel()
label.text = dataSource.snapshot().sectionIdentifiers[section].rawValue.capitalized
label.textColor = UIColor.black
return label
}
Run Code Online (Sandbox Code Playgroud)
这给了我 4 个标签堆叠在我的 tableView 顶部的标题单元格中。
我启动了 Dash 到 RTFD,我看到了tableView(titleForHeaderInSection:)另一种剥猫皮的方法。所以我把这个扔进去,而不是:
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试UICollectionViewDiffableDataSource为我的collectionView. 我的代码编译得很好,但是我第一次对它应用快照时一直遇到这个错误,并出现以下错误:
由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效参数不满足:self.supplementaryViewProvider || (self.supplementaryReuseIdentifierProvider && self.supplementaryViewConfigurationHandler)'
这是我的代码:
var groups: [Group] = [Group]()
var dataSource: UICollectionViewDiffableDataSource<Section, Group>!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
self.searchBar.delegate = self
self.groups = DummyData.groups
setupDataSource()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
performSearch(searchQuery: nil)
}
// MARK: - Helper Functions
func performSearch(searchQuery: String?) {
let filteredGroups: [Group]
if let searchQuery = searchQuery, !searchQuery.isEmpty {
filteredGroups = groups.filter { $0.contains(query: searchQuery) }
} else {
filteredGroups = groups …Run Code Online (Sandbox Code Playgroud) uikit uicollectionview swift5 diffabledatasource nsdiffabledatasourcesnapshot
可以通过哪些方式UICollectionViewDiffableDataSource重新加载标头?
我有一个集合视图,其中的标题显示用户详细信息,行显示帖子,模型是
struct PostUser {
var user: User
var post: Post
}
Run Code Online (Sandbox Code Playgroud)
当我通过快照更改属性时
var postUsers = [PostUser]() {
didSet {
self.applySnapshot(postUsers)
}
}
fileprivate func applySnapshot(_ postsUser: [PostUser]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, PostUser>()
snapshot.appendSections([.main])
snapshot.appendItems(postsUser)
self.datasource.apply(snapshot, animatingDifferences: true)
}
Run Code Online (Sandbox Code Playgroud)
行会重新加载,但补充标题不会重新加载。我可以更改标题的唯一方法是使“部分”成为模型的一部分,因此:
struct Section: Hashable {
var User: User
}
Run Code Online (Sandbox Code Playgroud)
我的应用快照现在变成
fileprivate func applySnapshot(_ postsUser: [PostUser]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, PostUser>()
snapshot.appendSections([Section(User: self.user)])
snapshot.appendItems(postsUser)
self.datasource.apply(snapshot, animatingDifferences: true)
}
Run Code Online (Sandbox Code Playgroud)
然后我单独设置用户
var user: User! = nil {
didSet {
self.applySnapshot(self.postUsers) …Run Code Online (Sandbox Code Playgroud) ios swift diffabledatasource uicollectionviewdiffabledatasource
我尝试为 中的每个部分添加标题UITableView,但在这种情况下UITableViewDiffableDataSource,我不知道应该在哪里做。我的代码的一部分:
private func prepareTableView() {
tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
dataSource = UITableViewDiffableDataSource<Sections, User>(tableView: tableView, cellProvider: { (tableView, indexPath, user) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = user.name
return cell
})
}
private func addElement(_ user: User) {
var snap = NSDiffableDataSourceSnapshot<Sections, User>()
snap.appendSections([.main, .second])
if isFirst {
users.append(user)
} else {
secondUsers.append(user)
}
snap.appendItems(users, toSection: .main)
snap.appendItems(secondUsers, toSection: .second)
isFirst.toggle()
dataSource.apply(snap, animatingDifferences: true, completion: nil)
dataSource.defaultRowAnimation = .fade …Run Code Online (Sandbox Code Playgroud) uitableview swift diffabledatasource nsdiffabledatasourcesnapshot
大家好???我正在将以下内容解析JSON为UITableView使用 aUITableViewDiffableDataSource进行漂亮的搜索动画。
JSON:https : //www.pathofexile.com/api/trade/data/items
这是回购:https : //github.com/laurentdelorme/PathOfData
从 JSON 中,我能够加载所有 13 个不同的类别,如模型文件中映射的那样。然后我能够将这些类别中的数据推送到另一个 tableView(使用 的那个UITableViewDiffableDataSource)并很好地显示所有内容。
但是,当我尝试将其内容推送到 DetailViewController 时,有一个类别会使我的应用程序崩溃,即初始ViewController.
这是我的模型:
struct ItemCategories: Codable {
var result: [ItemCategory]
}
struct ItemCategory: Codable {
var label: String
var entries: [Item]
}
struct Item: Codable, Hashable {
var name: String?
var type: String?
var text: String?
}
Run Code Online (Sandbox Code Playgroud)
这是我的 ViewController :
import UIKit
class ViewController: UITableViewController {
let urlString = "https://www.pathofexile.com/api/trade/data/items"
var categories …Run Code Online (Sandbox Code Playgroud) 我的应用程序提供了一个类似于 Apple 的表情符号键盘,其中表情符号按类别显示。我使用一个集合视图来呈现它,其中类别是部分。如果最近插入了表情符号,它应该出现在“常用”类别以及它通常所在的任何类别中。
这对我试图将我的集合视图转换为使用 a 来说是一个问题UICollectionViewDiffableDataSource,因为NSDiffableDataSourceSnapshot要求项目是唯一的。如果我做类似的事情
let snapshot = NSDiffableDataSourceSnapshot<Section, Emoji>()
snapshot.appendItems([thumbsUpEmoji], toSection: .frequents)
snapshot.appendItems([thumbsUpEmoji], toSection: .smileys)
dataSource.apply(snapshot)
Run Code Online (Sandbox Code Playgroud)
我收到类似的警告
插入的标识符已经存在;现有项目将被移动到此当前插入的位置。请注意,如果插入时项目不是唯一的,这将影响性能。
表情符号只出现在一个部分,而不是两个部分。如何将项目插入多个部分?
swift ×7
ios ×6
uitableview ×5
nsdiffabledatasourcesnapshot ×2
uikit ×2
diff ×1
ios13 ×1
json ×1
swift5 ×1