展开可选元素时出错

时间:2017-12-06 22:20:43

标签: json swift null optional

我有一个可选元素,但在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
}

2 个答案:

答案 0 :(得分:1)

如果avatarnil,代码会崩溃。您需要分两步创建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。