IOS 如果没有互联网连接,应用程序会在一行代码处崩溃,我该如何防止这种情况

IOS app crashes on a line of code if there's no internet connection, how can I prevent this

代码 this 和它在“try!”时崩溃,但我不知道如何捕获错误并且它是明确的,否则它将无法工作。

func downloadPicture2(finished: () -> Void) {          
    let imageUrlString = self.payments[indexPath.row].picture
    let imageUrl = URL(string: imageUrlString!)!
    let imageData = try! Data(contentsOf: imageUrl)
    cell.profilePicture.image = UIImage(data: imageData)
    cell.profilePicture.layer.cornerRadius = cell.profilePicture.frame.size.width / 2
    cell.profilePicture.clipsToBounds = true        
}

简短的回答是不要使用 try! - 使用 do/try/catch 并从 catch 子句中的问题中恢复。

例如-

func downloadPicture2(finished: () -> Void) {          
    cell.profilePicture.image = nil
    if let imageUrlString = self.payments[indexPath.row].picture, 
       let imageUrl = URL(string: imageUrlString) {
        do {
            let imageData = try Data(contentsOf: imageUrl)
            cell.profilePicture.image = UIImage(data: imageData)
        }
        catch {
            print("Error fetching image - \(error)")
        }
    }
    cell.profilePicture.layer.cornerRadius = cell.profilePicture.frame.size.width / 2
    cell.profilePicture.clipsToBounds = true        
}

现在您的代码在 url 无效或没有网络时不会崩溃,但是此代码仍然存在一些严重的问题。

Data(contentsOf:) 在获取数据时阻塞当前线程。由于您在主线程上执行,这将冻结用户界面并带来糟糕的用户体验。

苹果specifically warns not to do this

Important

Don't use this synchronous initializer to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.

相反,您应该使用异步网络操作,例如dataTask

此代码在 cell - 外部 属性 上运行。一旦您转向异步代码,您可能会同时为多个单元格获取图像。您应该将相关的 cell 传递给此函数以避免冲突。

网络的使用也不是特别有效;假设这是 table 或集合视图的一部分,单元格将在视图滚动时重复使用。发生这种情况时,您将重复获取相同的图像。某种本地缓存会更有效。

如果可以在您的项目中使用外部框架(即您的雇主没有明确禁止),那么我强烈建议您查看 SDWebImage or KingFisher 这样的框架。他们将使这项任务变得更加容易和高效。