1

我有多个 API 调用将在获取结果时更新 uitableview。UI 需要在 API 提供数据时更新。所有 API 调用都是异步的。数据必须以正确的顺序填充。API0 应该更新第 0 节,API1 应该更新第 1 节,依此类推。

我已经能够使用 2 个 API 来实现这一点,但是当我使用第 3 个 API 时,我会遇到崩溃。

请在下面找到我的代码:

    @IBOutlet weak var myTableView: UITableView!
var myDataSource: myTableDataSource!
var initialLoad = true
var tablD = [Int : [Any]]()
let queue = DispatchQueue(
    label: "com.affluvar.multipleAPI.MyQueue", // 1
    attributes: .concurrent)

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    myTableView.tableFooterView = UIView()
    API0()
    API1()
    API2()
}

//MARK: API methods
func API0(){
    queue.async {
        print("queue THREAD0")
        getData(offset: 0,limit: 10){
            (finalArray) in
            print("IN FIRST")
            for rest in finalArray{
                print(rest.name)
            }
            self.queue.sync {
                self.tablD.updateValue(finalArray, forKey: 0)
                self.myDataSource = myTableDataSource(data: self.tablD)
                print("SYNC DATASOURCE UPDATED 0")
                DispatchQueue.main.async {
                    if self.initialLoad == true{
                        self.initialLoad = false
                        self.myTableView.dataSource = self.myDataSource
                        print("TABLE RELOADING INITIAL ")
                        self.myTableView.reloadData()
                    }
                }
                self.saveData(data: finalArray, section: 0)
            }
        }

    }
}

func API1(){
    queue.async{
        print("queue THREAD1 ")
        getData(offset: 10,limit: 12){
            (finalArray1) in
            print("IN SECOND ")
            for rest in finalArray1{
                print(rest.name)
            }
            self.queue.sync{
                self.tablD.updateValue(finalArray1, forKey: 1)
                self.myDataSource = myTableDataSource(data: self.tablD)
                print("SYNC DATASOURCE UPDATED 1")
                DispatchQueue.main.async {
                    if self.initialLoad == true{
                        self.initialLoad = false
                        self.myTableView.dataSource = self.myDataSource
                        print("TABLE RELOADING INITIAL ")
                        self.myTableView.reloadData()
                    }
                }
                self.saveData(data: finalArray1, section: 1)
            }

        }
    }
}

func API2(){
    queue.async{
        print("queue THREAD2")
        getData(offset: 20,limit: 12){
            (finalArray1) in
            print("IN third")
            for rest in finalArray1{
                print(rest.name)
            }
            self.queue.sync{
                self.tablD.updateValue(finalArray1, forKey: 2)
                self.myDataSource = myTableDataSource(data: self.tablD)
                print("SYNC DATASOURCE UPDATED 2")
                DispatchQueue.main.async {
                    if self.initialLoad == true{
                        self.initialLoad = false
                        self.myTableView.dataSource = self.myDataSource
                        print("TABLE RELOADING INITIAL ")
                        self.myTableView.reloadData()
                    }
                }
                self.saveData(data: finalArray1, section: 2)
            }
        }
    }
}

func saveData(data:[userModel], section: Int){
        print("queue THREAD barrier ", section)
        //print("table datasrc entry:", self.myTableView.dataSource ?? "nil")
        DispatchQueue.main.sync {
                print("In else ", section)
                    print("sections before IN ELSE",self.myTableView.numberOfSections)
                    self.myTableView.dataSource = self.myDataSource
                    //self.myTableView.reloadData()
                    //self.myTableView.beginUpdates()
                    print("reloading section number:", section)
                    self.myTableView.reloadSections([section], with: .automatic)
                    print("sections AFTER in ELSE",self.myTableView.numberOfSections)
                    //self.myTableView.endUpdates()
        }
        print("CONTINUING QUEUE WORK")
}

以上是我的 viewController 代码。

这里的错误是->

2018-08-01 16:13:14.381174+0530 docAnywhere[4299:118229] *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.33.6/UITableView.m:13456 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource is not set'

表数据源类 ->>

class myTableDataSource: NSObject, UITableViewDataSource{
var userData = [Any]()
var tableData = [[Any]]()
var tablD = [Int : [Any]]()
init(data: [Int : [Any]]) {
    tablD = data
}
//MARK: Table methods
func numberOfSections(in tableView: UITableView) -> Int {
    //print("sections:", tablD.count)
    return 3
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("reload in progress")
    if let rows = tablD[section] as? [Any]{
        return rows.count
    }
    return 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "usersCell") as! usersCell
    let rowData = tablD[indexPath.section] as! [Any]
    let thisUser = rowData[indexPath.row] as? userModel// userData[indexPath.row] as? userModel
    cell.userName?.text = thisUser?.name ?? ""
    print("cell no", thisUser?.name ?? "", "at", indexPath.section, indexPath.row)
    if (indexPath.row == (rowData.count - 1)) {
        print("LAST CELL RELOAD COMPLETE HERE", indexPath.section)
    }
    return cell
}

}

有时错误是这样的:-

2018-08-01 16:47:53.467219+0530 docAnywhere[6084:147469] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete section 0, but there are only 0 sections before the update'

注意:: 在 2 个 API 调用和调度组不能使用的情况下它工作正常,因为 UI 需要在任何 API 调用完成并且数据可用时立即更新。多个数组或数据源不能用于多个 API。

4

1 回答 1

0

您正在崩溃,因为您不断更改 tableView 数据源。我在您的代码清单中遗漏了一段代码......如果您可以重新设计数据源,那么您不必像那样更改它,您会没事的。例如,您可以使用 api1 重新加载“1”部分,当它完成后,您只需将您从该 api 调用收到的项目附加到第 1 部分...所有这些听起来可能令人困惑 :) 我的意思是,不要更改数据源...

于 2018-08-01T22:40:41.640 回答