Fatal error: Index out of range when receive nil data which I marked as optional

Fatal error: Index out of range when receive nil data which I marked as optional

您好,我有一些问题与我的数据模型数组中的索引超出范围有关。只要 images = [] 为空,应用程序就会崩溃。

所以这是我的 UIViewController 的 table 视图中的代码。

        
        if let urlString = vehicleList?._embedded.userVehicles[indexPath.row].images[0] {
            
            let url = URL(string: urlString)
            cell.vehicleImage.kf.setImage(with: url, placeholder: nil)
        } else {
            let url = URL(string: "https://vehicleimage-insure.s3-eu-west-1.amazonaws.com/defaultCarIcon.png")
            cell.vehicleImage.kf.setImage(with: url, placeholder: nil)
        }

这是我的图像数据模型 属性,我已将其标记为可选:

struct UserVehicles: Codable {
    let id: String 
    let images: [String?]
    let userId: String
}

错误信息如下图:

我查看了调试输出,如下:

我的意思是我写了if let语法,难道不应该捕获错误吗?请给我一些提示,我该如何解决这个错误?

if let 语句将检查可选语句是否为 nil。

当您尝试在不存在的索引处访问数组元素时,它不会 return nil 但您会收到索引超出范围错误。

如果你想安全地访问数组中的元素,你应该在访问索引之前执行数组大小检查。

if list.count > 0 {
    let listItem = list[0]
    // do something
}

或者为 Collection 实现安全访问的扩展。

extension Collection {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.
    /// Sample: `list[safe: index]`
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

然后你可以使用 if let ,因为这个下标 return 是可选的。

if let listItem = list[safe: 0] {
    // do something
}

让我们考虑一下所有可能出错的地方:

if let urlString = vehicleList?._embedded.userVehicles[indexPath.row].images[0]

嗯,vehicleList 可能是 nil。但这没问题; if let 负责处理。

接下来,您有一个数组引用 userVehicles[indexPath.row]。好吧,我想数组中可能没有那么多对象。

最后,您得到了另一个数组引用,images[0]。但是数组可能是空的。

所以我们可以安全地检查所有这些:

if let vList = vehicleList, // avoid `nil`
    vList._embedded.userVehicles.count > indexPath.row,
    vList._embedded.userVehicles[indexPath.row].images.count > 0 {
        // now it is safe
        let urlString = vlist._embedded.userVehicles[indexPath.row].images[0]
        let url = URL(string: urlString)
        cell.vehicleImage.kf.setImage(with: url, placeholder: nil)
    } else {
        // use placeholder URL
}
       

(如果您的某些对象本身可能 nil,您可能需要改进该代码,但您已经知道如何做到这一点。)