对不起,我是初学者学习IOS
我的tableView和重装数据有问题
当我经常打电话给#34; 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
}
}
的ViewController:
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
}
}
答案 0 :(得分:1)
问题很可能是由于您目前如何使用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时使用的数据进行任何更改,除非在重新加载之前在主线程juste上同步。