[英]iOS: Invalid update: invalid number of rows in section 0
I create a table view that every time I scroll to the end of table it will show shimmer in table section 1 for waiting the api load a new data.我创建了一个表格视图,每次滚动到表格末尾时,它都会在表格第 1 部分显示微光,等待 api 加载新数据。 After api finish load data, new data will append to the array that use for contain all data that be show to table view on section 0, then reload the table view to update the section 1 numberOfRowsInSection to 0 to hide the shimmer and update the section 0 numberOfRowsInSection
api 完成加载数据后,新数据将 append 到用于包含在第 0 节上显示到表视图的所有数据的数组中,然后重新加载表视图以将第 1 节 numberOfRowsInSection 更新为 0 以隐藏闪光并更新节0 numberOfRowsInSection
So this is the example of my code所以这是我的代码示例
fileprivate var data = [dataArray]() {
didSet {
guard !data.isEmpty else {
return
}
tableView.reloadData()
tableView.layoutIfNeeded()
view.layoutIfNeeded()
}
}
fileprivate var isLoadingMore: Bool = false {
didSet {
tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
tableView.layoutIfNeeded()
tableViewHeightConstraint.constant = tableView.contentSize.height + 60.0
view.layoutIfNeeded()
}
}
fileprivate func loadData() {
if let size = self.paging.totalSize,
data.count >= size {
return
}
let limit = paging.limit
let offset = paging.offset
guard !isLoadingMore else { return }
isLoadingMore = true
controller.requestContent(
completion: { [weak self] (success, offset, size, data) in
DispatchQueue.main.async {
self?.isLoadingMore = false
guard let list = data,
let data = list as? [dataArray],
let size = size else {
return
}
if success {
if self?.paging.currentPage == 0 {
self?.data = data
if self?.scrollView.frame.size.height >= self?.scrollView.contentSize.height {
self?.paging.totalSize = size
self?.paging.currentPage += 1
self?.loadData()
return
}
} else {
self?.data.append(contentsOf: songs)
}
self?.paging.totalSize = size
self?.paging.currentPage += 1
} else {
self?.alert("failed")
}
}
})
}
fileprivate func loadDataFromCoreData() {
isLoadingMore = false
let context = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let dataFromCoreData = Datas.fetchData(context: context).filter({$0.isSaved})
songs = dataFromCoreData.map({ dataArray(song: $0) })
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return data.count
case 1:
return isLoadingMore ? 1 : 0
default:
return 0
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height){
loadData()
}
}
func setupForCeckingAvailableData() {
utility.checkInternetAccess = { [weak self] result in
if result {
self?.paging = Paging()
self?.loadData()
} else {
self?.loadDataFromCoreData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupForCeckingAvailableData()
}
so some time when I first time load or try fetch new data by scrolling to the end of table I got a crash with the message is因此,当我第一次加载或尝试通过滚动到表末尾来获取新数据时,我遇到了崩溃的消息是
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (10), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
So what the cause of it?那么它的原因是什么呢? Why got that crash even though I already use
reloadData()
every time I append a new data to variable data
.为什么即使我已经使用
reloadData()
每次我 append a new data to variable data
都会发生崩溃。 Should I change reloadData()
to我应该将
reloadData()
更改为
tableView.beginUpdates()
tableView.insertRows(at: indexPaths, with: .automatic)
tableView.endUpdates()
? ? if that so, is that the crash cause
insertRows
only refresh specific row and section so no take a loot of time to refresh table with a loot of datas??如果是这样,那是崩溃导致
insertRows
只刷新特定的行和部分,所以不需要花费大量时间来刷新带有大量数据的表吗? That's all of my question, Thank you这就是我的全部问题,谢谢
I just want to point out something else.我只是想指出点别的。 Generally speaking, Singletons are Evil and I avoid them like the plague.
一般来说,单身人士是邪恶的,我像避免瘟疫一样避免他们。
This is a real big code smell and would advise you to stop using this type of code:这是一个真正的大代码气味,建议您停止使用这种类型的代码:
TableView.beginUpdates()
TableView.insertRows(at: indexPaths, with: .automatic)
TableView.endUpdates()
See What is so bad about singletons?看看单例有什么不好? there are many more blog posts about it.
还有更多关于它的博客文章。
after I do some research I found a clue.在我做了一些研究后,我发现了一个线索。 I add
tableView.reloadData()
before tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
because when I see the crashlytic crash happend at tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
我在
tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
) 之前添加tableView.reloadData()
) 因为当我看到在tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
.automatic) 发生崩溃时
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.