我有一个可选元素,但是在表观视图中显示上述元素时面临错误。作为参考,此元素是从JSON API feed获得的图像。我了解使用使用元素使用的力量!这不是一个好主意,但这是Xcode建议的,没有其他选择。如果我遵循它的建议,应用程序会崩溃,显示"在解开可选值的同时意外发现了无零。" 有人知道我如何从URL显示图像。这是我到目前为止的代码。
struct PlayerStats:Decodable {
let personaname: String?
let score: Double?
let solo_competitive_rank: Int?
let avatar: String?
}
问题在于" avatar"元素,在cellforrowat func中。
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
}
如果avatar
为nil
,则代码崩溃。您需要在两个步骤中创建URL
if let avatar = rank[indexPath.row].avatar,
let imageURL = URL(string: avatar) { ...
另外,将avatar
直接解码到URL,JSONDecoder
可以
let avatar: URL?
然后您可以缩短代码
if let imageURL = rank[indexPath.row].avatar {
,您强烈不鼓励使用Dávid提到的同步Data(contentsOf:
API。使用异步URLSession
除了您需要安全地解开可选的avatar
属性以外,您的代码有几个概念问题。
首先,您绝对不应在tableView(_:cellForRowAt:)
内执行异步操作,因为这是一种同步方法,因此UITableViewCell
将在可以从网络URL下载图像之前返回。您需要在单独的函数中执行图像下载并重新加载表视图(或至少在相应的行/部分)后完成执行。
其次,不要使用初始化器Data(contentsOf:)
从Internet下载内容。即使通过派遣Data(contentsOf: imageURL)
,您也不会阻止主线程,但不应将数据初始化器用于从Internet下载内容。该初始化程序仅应用于从本地文件URL加载内容,而不是网络URL。