我有UITableView来显示文件列表。每个文件名都使用特定的代码组合进行编码,为了获得真实的文件名,我必须使用当前文件名来调用服务器端。

是否可以在cellForRowAt indexPath表视图委托函数上调用此类操作?

var files: [URL]!

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "FilesManagerCell", for: indexPath) as? FilesManagerCell {
            let currentFile = files[indexPath.row]

            APIClient.getFileInfo(patientId: currentFile.lastPathComponent, onSuccess: { (response) in
                cell.filenameLabel.text = response.file.fileName
                cell.createdDateLabel.text = response.file.creationDate
                cell.fileSizeLabel.text = response.file.fileSizeWithToken
                cell.filePath = currentFile
                return cell <- Here I get expected error

           }, onError: { (errorResponse, errorString) in
        })

        }
        return UITableViewCell()

最佳答案

cellForRowAt要求您同步返回单元格。

通过传递每个单个单元格的责任来自定义您的单元格,以根据请求加载其内容-从而重新加载其自己的UI。

为了显示:

这将是您的单元(已连接插座):

class FilesManagerCell: UITableViewCell {

    @IBOutlet private weak var filenameLabel: UILabel!
    @IBOutlet private weak var createdDateLabel: UILabel!
    @IBOutlet private weak var fileSizeLabel: UILabel!

    var filePath: URL! {
        didSet {
            fetchContents()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        //Here you should create the "Loading behavior", i.e:
        self.filenameLabel.text = "Loading"
        self.createdDateLabel.text = "Loading"
        self.fileSizeLabel.text = "Loading"
    }

    private func fetchContents() {
        APIClient.getFileInfo(patientId: filepath.lastPathComponent, onSuccess: { response in
            DispatchQueue.main.async {
                self.filenameLabel.text = response.file.fileName
                self.createdDateLabel.text = response.file.creationDate
                self.fileSizeLabel.text = response.file.fileSizeWithToken
            }
        }, onError: { (errorResponse, errorString) in
            //Customize your error code, i.e:
            DispatchQueue.main.async {
                self.filenameLabel.text = "Error"
                self.createdDateLabel.text = "Error"
                self.fileSizeLabel.text = "Error"
            }
        })
    }
}

和您的tableView cellForRowAt实现:
//...
var files: [URL]!

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "FilesManagerCell", for: indexPath) as? FilesManagerCell {
        let currentFile = files[indexPath.row]
        cell.filePath = currentFile
    }

    return UITableViewCell()
}
//...

编辑:将这个职责委托给单元格本身没有问题,但是请注意,当一个单元格被重用时,它将在设置fetchContents()属性时触发一个新的filePath,从而触发一个新的API调用-但是会某些数据“不一致”,因为虽然提取不返回,但它将具有先前的提取内容。解决此问题的一种方法是,每次设置filePath时都将其重置为“正在加载”状态,如下所示:

    var filePath: URL! {
        didSet {
            // Reset the current fields
            self.filenameLabel.text = "Loading"
            self.createdDateLabel.text = "Loading"
            self.fileSizeLabel.text = "Loading"

            // And then fetch the contents
            fetchContents()
        }
    }

关于ios - UITableView cellForRowAt中的API异步调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53102559/

10-12 14:30