UITableView cellForRowAt中的API异步调用



我有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"
}
})
}
}

和您的表查看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()
}
//...

编辑:将此责任委托给单元格本身没有问题,但请注意,当单元格被重用时,它将在设置filePath属性时触发新的fetchContents(),从而触发新的API调用-但会有一些数据"不一致",因为当fetch不返回时,它会具有以前的fetch内容。一个解决方案可以是每次设置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()
}
}

最新更新