尝试插入行时,tableview崩溃,显示“Invalid update:Invalid number of rows in section 0”。更新之后(1)中包含的现有区段中的行数必须等于更新之前(0)中包含的那一行的行数,加上或减去从该区段插入或删除的行数(插入0,删除0),加上或减去进入或退出该区段的行数(0移入),0已移出)
当我试图删除一行“试图将第0行插入第0节,但更新后第0节中只有0行”时,它也会崩溃
这是一个从Github克隆的名为antidote.SDK,它只尝试使用tableview.reloaddata()而不是开始和结束更新,反之亦然。
同样的链接是:https://github.com/Antidote-for-Tox/Antidote
友好列表控制器
super.viewDidLoad()
let friends = submanagerObjects.friends()
let requests = submanagerObjects.friendRequests()
dataSource = FriendListDataSource(theme: theme, friends:
friends, requests: requests)
dataSource.delegate = self
tableView.tableFooterView = UIView()
updateViewsVisibility()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateViewsVisibility()
}
extension FriendListController: FriendListDataSourceDelegate {
func friendListDataSourceBeginUpdates() {
tableView.beginUpdates()
}
func friendListDataSourceEndUpdates() {
tableView.endUpdates()
updateViewsVisibility()
}
func friendListDataSourceInsertRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.insertRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceDeleteRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.deleteRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceReloadRowsAtIndexPaths(_ indexPaths: [IndexPath]) {
tableView.reloadRows(at: indexPaths, with: .automatic)
}
func friendListDataSourceInsertSections(_ sections: IndexSet) {
tableView.insertSections(sections, with: .automatic)
}
func friendListDataSourceDeleteSections(_ sections: IndexSet) {
tableView.deleteSections(sections, with: .automatic)
}
func friendListDataSourceReloadSections(_ sections: IndexSet) {
tableView.reloadSections(sections, with: .automatic)
}
func friendListDataSourceReloadTable() {
tableView.reloadData()
}
}
extension FriendListController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: FriendListCell.staticReuseIdentifier) as! FriendListCell
let model = dataSource.modelAtIndexPath(indexPath)
cell.setupWithTheme(theme, model: model)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.numberOfSections()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.numberOfRowsInSection(section)
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return dataSource.sectionIndexTitles()
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return dataSource.titleForHeaderInSection(section)
}
func tableView(_ tableView: UITableView, commit editingStyle:
UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let title: String
switch dataSource.objectAtIndexPath(indexPath) {
case .request:
title = String(localized:"delete_contact_request_title")
case .friend:
title = String(localized:"delete_contact_title")
}
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: String(localized: "alert_cancel"), style: .default, handler: nil))
alert.addAction(UIAlertAction(title: String(localized: "alert_delete"), style: .destructive) { [unowned self] _ -> Void in
switch self.dataSource.objectAtIndexPath(indexPath) {
case .request(let request):
self.submanagerFriends.remove(request)
case .friend(let friend):
do {
let chat =
self.submanagerChats.getOrCreateChat(with: friend)
try self.submanagerFriends.remove(friend)
self.submanagerChats.removeAllMessages(in: chat, removeChat: true)
} catch let error as NSError {
handleErrorWithType(.removeFriend, error: error)
}
}
})
present(alert, animated: true, completion: nil)
}
}
}
FriendListDataSource
private extension FriendListDataSource {
func addNotificationBlocks() {
requestsToken = requests?.addNotificationBlock { [unowned self] change in
switch change {
case .initial:
break
case .update(let requests, let deletions, let insertions, let modifications):
guard let requests = requests else { return }
if deletions.count > 0 {
self.delegate?.friendListDataSourceReloadTable()
return
}
self.delegate?.friendListDataSourceBeginUpdates()
let countAfter = requests.count
let countBefore = countAfter - insertions.count + deletions.count
if countBefore == 0 && countAfter > 0 {
self.delegate?.friendListDataSourceInsertSections(IndexSet(integer: 0))
} else {
self.delegate?.friendListDataSourceDeleteRowsAtIndexPaths(deletions.map { IndexPath(row: $0, section: 0)} )
self.delegate?.friendListDataSourceInsertRowsAtIndexPaths(insertions.map { IndexPath(row: $0, section: 0)} )
self.delegate?.friendListDataSourceReloadRowsAtIndexPaths(modifications.map { IndexPath(row: $0, section: 0)} )
}
self.delegate?.friendListDataSourceEndUpdates()
case .error(let error):
fatalError("\(error)")
}
}
它应该在没有崩溃的情况下工作。它在插入和删除时崩溃。前者产生“无效更新:0节中的行数无效”。更新之后(1)中包含的现有区段中的行数必须等于更新之前(0)中包含的那一行的行数,加上或减去从该区段插入或删除的行数(插入0,删除0),加上或减去进入或退出该区段的行数(0移入),0已移出)
后者生成:“试图将行0插入到节0中,但更新后节0中只有0行。”
如有任何帮助,我们将不胜感激。
最佳答案
根据UITableView类,您必须使用以下选项之一:performBatchUpdates(_:completion:)
(link)func beginUpdates()
(link)然后func endUpdates()
(link)
必须在批更新块内(或在开始和结束更新函数之间)执行所有更新(包括数据源更新-不仅是插入/删除/移动/重新加载)
这样你就能避免撞车。
例如:
var dataSource: [Int] = [1, 2, 3]
tableView.beginUpdates()
dataSource.append(4)
tableView.insertRows(at: [IndexPath(row: 3, section: 0)], with: .automatic)
tableView.endUpdates()
关于swift - 获取“NSInternalInconsistencyException”,在插入和删除时,第0节中的无效行数错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57158143/