在Swift 4中加载图像时防止非200响应

时间:2018-01-28 16:35:05

标签: swift swift4

使用Swift 4加载外部图像时,如果URL在下面的代码块中以非200响应进行响应,则会遇到问题。例如,在提供发送401的图像时,应用程序在此示例的第2行崩溃,并出现以下错误:

Thread 29: Fatal error: Unexpectedly found nil while unwrapping an Optional value

如何解决此问题并提供其他网址?

let imageUrl:URL = URL(string: imageUrlString)!
let imageData:NSData = NSData(contentsOf: imageUrl)!
let imageView = UIImageView(frame: CGRect(x:11, y:90, width:80, height:80))

// When from background thread, UI needs to be updated on main_queue
DispatchQueue.main.async {
    let image = UIImage(data: imageData as Data)
    imageView.image = image
    imageView.layer.zPosition = 1
    imageView.contentMode = UIViewContentMode.scaleAspectFit
    self.view.addSubview(imageView)
}

2 个答案:

答案 0 :(得分:1)

来自NSData(contentsOf:文档(遗憾的是Data中缺少此注释):

enter image description here

因此,请认真对待此说明并使用URLSession

guard let imageUrl = URL(string: imageUrlString) else { // ... handle the `nil` case }

let task = URLSession.shared.dataTask(with: imageUrl) { data, response, error in
    if let error = error { print(error); return }
    guard let response = response as? HTTPURLResponse else { print("Response is not HTTPResponse"); return }
    if response.statusCode != 200 { print("response error:",  response.statusCode); return }
    DispatchQueue.main.async {
        let image = UIImage(data: data!) // `data` can be unwrapped safely if `error` is nil
        imageView.image = image
        imageView.layer.zPosition = 1
        imageView.contentMode = .scaleAspectFit
        self.view.addSubview(imageView)
    }
}
task.resume()

您可以单独处理errorresponse。如果errornil,则data为非零,反之亦然。

答案 1 :(得分:0)

NSData(contentsOf:url)是一个可用的初始化器,这意味着它返回一个可选的NSData实例,并且它失败的一个实例是非200响应。

然后,您的代码尝试使用'!'强行解开它。这就是你得错的原因。

首先,你需要决定如果它失败了怎么办,即你不打算显示图像,显示默认图像等等。

然后更改您的代码以考虑到这一点。所以像这样:

let imageUrl:URL = URL(string: imageUrlString)!
if let imageData = NSData(contentsOf: imageUrl) {
    let imageView = UIImageView(frame: CGRect(x:11, y:90, width:80, height:80))

    // When from background thread, UI needs to be updated on main_queue
    DispatchQueue.main.async {
        let image = UIImage(data: imageData as Data)
        imageView.image = image
        imageView.layer.zPosition = 1
        imageView.contentMode = UIViewContentMode.scaleAspectFit
        self.view.addSubview(imageView)
    }
} else {
    // Do whatever you want if getting the image fails, e.g. non 200 response.
}

修改

正如已经指出的那样,NSData(contentsOf :)不应该用于网络相关的查询,但即使对于本地查询,它仍然可能失败,所以我会留下答案,因为这是原始错误的原因。