致命错误:收到我标记为可选的零数据时,索引超出范围

问题描述

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

这是我UIViewController的表格视图中的代码

        
        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)
        }

这是我用于image属性的数据模型,我将其标记为可选:

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

错误消息如下图:

enter image description here

我检查了调试输出,如下所示:

enter image description here

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

解决方法

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

当您尝试在不存在的索引处访问数组的元素时,它不会返回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 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,则可能需要改进该代码,但是您已经知道该怎么做。)