我有一个可选元素,但在tableview中显示所述元素时遇到错误。作为参考,此元素是从JSON API提要获得的图像。我明白用力展开一个元素!这不是一个好主意,但它是xcode建议我做的,没有其他选择。如果我按照其建议,应用程序崩溃,在展开“可选”值时显示"意外发现nil。" 是否有人知道如何显示网址中的图片。这是我到目前为止的代码。
struct PlayerStats:Decodable {
let personaname: String?
let score: Double?
let solo_competitive_rank: Int?
let avatar: String?
}
问题出在" avatar"元素,在cellForRowAt函数中。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "rankCell") as? RankTableViewCell else { return UITableViewCell() }
cell.nameLabel.text = rank[indexPath.row].personaname
if let imageURL = URL(string: rank[indexPath.row].avatar) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
guard let avatar = UIImage(data: data) else { return }
DispatchQueue.main.async {
cell.avatarImage.image = avatar
}
}
}
}
return cell
}
答案 0 :(得分:1)
如果avatar
为nil
,代码会崩溃。您需要分两步创建URL
if let avatar = rank[indexPath.row].avatar,
let imageURL = URL(string: avatar) { ...
或者直接将avatar
解码为网址,JSONDecoder
可以
let avatar: URL?
然后你可以缩短代码
if let imageURL = rank[indexPath.row].avatar {
强烈建议您不要使用Dávid提到的同步Data(contentsOf:
API。使用异步URLSession
答案 1 :(得分:1)
除了您需要安全地解包可选的avatar
属性这一事实外,您的代码还存在一些概念性问题。
首先,您永远不应该在tableView(_:cellForRowAt:)
内执行异步操作,因为这是一种同步方法,因此在从网络URL下载图像之前将返回UITableViewCell
。在异步操作完成执行后,您需要在单独的函数中执行映像下载并重新加载表视图(或至少相应的行/部分)。
其次,请勿使用初始化程序Data(contentsOf:)
从Internet下载内容。即使通过调度Data(contentsOf: imageURL)
,您也不会阻止主线程,数据的初始化程序不应用于从Internet下载内容。该初始化程序仅应用于从本地文件URL加载内容,而不是网络URL。