Search code examples
swiftnulloption-typeiso

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


Hi I have some issue relate to index out of range in a array of my data model. As long as the images = [] is empty, the app crashes.

so this is the code in my UIViewController's table view.

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

this is my data model for the image property, I have marked it optional:

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

error message is as below picture:

enter image description here

I checked the debug output, as follows:

enter image description here

I mean I made the if let syntax, shouldn't the error be captured? Please give me some hints how can I fix this error?


Solution

  • Let's consider all the places where this can go wrong:

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

    Well, vehicleList might be nil. But that's no problem; the if let takes care of that.

    Next, you've got an array reference userVehicles[indexPath.row]. Well, I suppose there might not be that many objects in the array.

    Finally, you've got another array reference, images[0]. But the array might be empty.

    So we can check all of those safely:

    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
    }
           
    

    (You might need to improve on that code if some of your objects are themselves possibly nil, but you already know how to do that.)