Swift 3:在将数据放入UITableView之前预加载数据

时间:2017-06-21 17:48:30

标签: ios uitableview asynchronous swift3

我有一个应用程序,它将从API获取正好100个字符串并将它们放入UITableView。我希望首先将数据预加载到一个数组中,然后,一旦数组完全填充了100个条目,就将数据加载到表中。

由于异步API调用,在表视图开始填充其单元格之前,似乎无法将数据加载到数组中。主要是,我首先难以从封闭中获取数据。

这是APIAgent类中定义的API调用:

func getAPIData(_ requestType: String, completionHandler: @escaping (Data) -> ()) {
    let requestURL: URL = URL(string : baseURL + requestType)!
    let currentSession = URLSession.shared
    let task = currentSession.dataTask(with: requestURL) { (data, response, error) in
        completionHandler(data!)
    }
    task.resume()
}

这是UITableView使用它的方式:

protocol AsyncHelper {
    func getData(data: Any)
}

class TableViewController: UITableViewController, AsyncHelper {
    var dataEntries: [String] = []

    func getData(data: Data) {
        let entry: String = String(describing: data)
        dataEntries.append(entry) 
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        for i in 1...100 {
            apiAgent.getAPIData("entry" + String(i), entry: { entry in
                self.getData(data: entry)
            })
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "EntryCell", for: indexPath) as! EntryCell

        let entry: String = dataEntries[indexPath.row] // index out of range error

        DispatchQueue.main.async {
            // add Strings to cell here
        }

        return cell
    }
}

因此,似乎在将数据填充到dataEntries数组之前生成了单元格。如何在填充dataEntries之前阻止UITableView生成单元格。

2 个答案:

答案 0 :(得分:0)

试试这个:

m <- matrix(data = c(18, 29, 13, 56, 64, 23, 56, 92, 
                     23, 65, 28, 54, 46, 82, 46, 92),
            nrow = 4, byrow = TRUE)

m[3:4, 1:2] <- 0
m[1:2, 3:4] <- 0
m
#     [,1] [,2] [,3] [,4]
#[1,]   18   29    0    0
#[2,]   64   23    0    0
#[3,]    0    0   28   54
#[4,]    0    0   46   92

答案 1 :(得分:0)

如果您打算使用闭包,则不需要协议。您可以将网络代码更改为:

var songData = [Data]

func getAPIData(_ requestType: String, completionHandler: @escaping ([Data]) -> ()) {
let requestURL: URL = URL(string : baseURL + requestType)!
let currentSession = URLSession.shared
let task = currentSession.dataTask(with: requestURL) { (data, response, error) in
    songData.append(data!)

    if (songData.count == 100) {
        completionHandler(songData)
    }
}
task.resume()
}

这将确保只有在加载了所有100个数据元素后才会调用getData()tableView.reloadData()

仅供参考 - tableView.reloadData()将重新加载几乎所有必须处理您的表格视图的内容。您的numberOfRowsnumberOfSectionscellForRow都将再次被调用。这将使用更新的dataEntries

重新创建tableView