gpt4 book ai didi

ios - 在 GCD 主要威胁中频繁调用 "tableView.reloadData"得到崩溃错误 "Index out of range"

转载 作者:行者123 更新时间:2023-11-28 15:21:58 24 4
gpt4 key购买 nike

对不起,我是IOS初学者。
我的 tableView 和重新加载数据有问题。
当我频繁调用“getData”时,我会崩溃并报错。
但我不知道我的数据在哪里导致崩溃。
我想我先调用了 reloadData,然后 list.count 已经在全局线程中改变了
有什么建议可以避免吗?
谢谢。

崩溃日志:

fatal error: Index out of range

型号:

class ChatroomList:Model {

var all:[Chatroom] {
var rooms:[Chatroom] = [Chatroom]()
self.chatrooms.forEach({ (id,chatroom) in
if showType.contains(chatroom.type) {
rooms.append(chatroom)
}
})
return rooms
}
}

View Controller :

import RxCocoa
import RxSwift
import Alamofire

class ListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

let chatrooms:ChatroomList = ChatroomList()
var list:[Chatroom] = [Chatroom]()
var subscribe:Disposable?

override func viewDidLoad() {
super.viewDidLoad()

self.tableView.dataSource = self
self.tableView.delegate = self

}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

subscribe = rooms.notifySubject.subscribe({ json in
self.getData() //here is called frequently
})
self.getData()
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

subscribe?.dispose()
}

func getData() {

var idList:[String] = []

self.list.removeAll()
self.list = chatrooms.all

guard self.list.isEmpty == false else {
return
}

DispatchQueue.global().async() {

self.list.sort(by: { (a,b) in
if a.message.datetime.isEmpty {
return false
}

return a.message.datetime > b.message.datetime
})

self.list = self.list.filter { (chatroom) -> Bool in
if chatroom.id.isEmpty {
return true
}
if idList.contains(chatroom.id) {
return false
}
idList.append(chatroom.id)
return true
}

DispatchQueue.main.sync() {

self.tableView.reloadData()
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if list[indexPath.row].type == .city {

let cell: ChatroomCityTableViewCell = ChatroomCityTableViewCell(style: .default, reuseIdentifier: nil)

cell.loadByCityChatroom(chatroom: list[indexPath.row], cityId: list[indexPath.row].cityId)

return cell
}else{

let cell: ChatroomTableViewCell = ChatroomTableViewCell(style: .default, reuseIdentifier: nil)
cell.loadByChatroom(chatroom: list[indexPath.row])

return cell
}
}

最佳答案

问题很可能是由您当前使用 GCD(Grand central dispatch)的方式引起的。

重新加载时,tableView 会询问许多不同的问题,例如行数和每行的单元格。如果数据在其中一个调用之间发生变化,则会导致不一致异常,因为它试图添加或删除一些不再代表数据的行。

当您的 getData 函数可以在任何给定时间更改列表时,在主线程上异步重新加载 tableView 将导致上述错误。

解决方案并不简单,您需要重新考虑如何更新列表,使其在 tableView 重新加载其数据时不会发生变化。

您可以尝试做的一件事是:

func getData() {
// You cannot clear or change self.list here

guard !chatrooms.all.isEmpty else { return }

DispatchQueue.global().async() {
let updatedData = process(newData: self.chatrooms.all)

DispatchQueue.main.sync() {
self.list = updatedData
self.tableView.reloadData()
}
}
}

private func process(newData data: [Chatroom]) -> [Chatroom] {
// Do all your logic without making any changes to self.list
}

关键是永远不要对重新加载 tableView 时使用的数据进行任何更改,除非在重新加载之前在主线程上同步。

关于ios - 在 GCD 主要威胁中频繁调用 "tableView.reloadData"得到崩溃错误 "Index out of range",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45828649/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com