我有一个可选元素,但在表视图中显示上述元素时会遇到错误。作为参考,此元素是从JSON提要中获取的图像。我理解这个力用一个元素展开!这不是一个好主意,但这正是xcode建议我做的,没有给我其他的选择。如果我遵循它的建议,应用程序就会崩溃,显示“意外地找到了零,而打开了一个可选的值”。让任何人都知道我如何从URL中显示图像。这是我到目前为止所掌握的代码。
struct PlayerStats:Decodable {
let personaname: String?
let score: Double?
let solo_competitive_rank: Int?
let avatar: String?
}
问题在于cellForRowAt函数中的"avatar“元素。
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
}
发布于 2017-12-06 14:26:39
如果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
发布于 2017-12-06 14:42:56
除了需要安全地展开可选的avatar
属性这一事实之外,您的代码还存在一些概念性问题。
首先,您不应该在tableView(_:cellForRowAt:)
中执行异步操作,因为这是一个同步方法,所以在从网络URL下载映像之前将返回UITableViewCell
。在异步操作完成执行后,您需要在一个单独的函数中执行映像下载,并重新加载表视图(或至少相应的行/节)。
其次,不要使用初始化器Data(contentsOf:)
从互联网下载内容。即使通过发送Data(contentsOf: imageURL)
,您也不会阻塞主线程,数据初始化器不应该用于从internet下载内容。该初始化器只应用于从本地文件URL加载内容,而不是网络URL。
https://stackoverflow.com/questions/47684417
复制相似问题