Home > database >  Swift Core Data - handling empty fetch result
Swift Core Data - handling empty fetch result

Time:02-16

I have a simple entity, a stationID and a type, both Strings

I use this method to search for a type for a given stationID,

 func returnStationType(stationTypeId: String) -> PersistantStationType {
        
        let context = container.viewContext
        
        let request = PersistantStationType.fetchRequest() as NSFetchRequest<PersistantStationType>
        request.predicate = NSPredicate(format: "%K == %@", #keyPath(PersistantStationType.stationId), stationTypeId as CVarArg)
        
        do {
            
            let result = try context.fetch(request)
            if result.count != 0 {
                
                let fetchedStationType = result.first!
                
                return fetchedStationType
                
            } else { print("4 Fetch result was empty for specified stationid: \(String(describing: stationTypeId))")
                
            }
            
        } catch { print("Fetch on goal id: \(String(describing: stationTypeId)) failed. \(error)") }
        
        
        return PersistantStationType.init()
    
    }

I call the method here:

let persistentStationType = persistenceController.returnStationType(stationTypeId: closestStation.id)
                
                let stationType = persistentStationType.type?.lowercased().capitalized
                
                let realName = helper.returnRealName(stationType: stationType ?? "None")
                
                let imageName = helper.returnStationTypeImage(stationType: stationType ?? "None")

If a stationId is not found - so empty result I get a crash in the code(Bad Exec/ Access) where I call the method - not in the method itself. (I'm not surprised by this but i'm not sure how to handle it)

I can't use if let on the method .. .it's not an optional. Should I be returning an empty object and check for It when the fetch result is empty?

Thanks for any help.

CodePudding user response:

I would declare the function to return an optional and return nil when nothing is found

func returnStationType(stationTypeId: String) -> PersistantStationType? {
    let context = container.viewContext

    let request: NSFetchRequest<PersistantStationType> = PersistantStationType.fetchRequest()
    request.predicate = NSPredicate(format: "%K == %@", #keyPath(PersistantStationType.stationId), stationTypeId)

    do {
        let result = try context.fetch(request)

        if result.count != 0 {
            return result[0]
        } else {
            print("4 Fetch result was empty for specified stationid: \(String(describing: stationTypeId))")
            return nil
        }
    } catch {
        print("Fetch on goal id: \(String(describing: stationTypeId)) failed. \(error)")
        return nil
    }
}

If on the error hand it is considered an error if more than one objects (or none) exists for an id then it would be better to throw an error in those situations

func returnStationType(stationTypeId: String) throws -> PersistantStationType {
    let context = container.viewContext

    let request: NSFetchRequest<PersistantStationType> = PersistantStationType.fetchRequest()

    request.predicate = NSPredicate(format: "%K == %@", #keyPath(PersistantStationType.stationId), stationTypeId)

    do {
        let result = try context.fetch(request)

        switch result.count {
        case 0:
            throw FetchError("No station type found for id \(stationTypeId)")
        case 1:
            return result[0]
        default:
            throw FetchError("Multiple station types found for id \(stationTypeId)")
        }
    } catch let error as NSError {
        throw FetchError(error.localizedDescription)
    }
}

struct FetchError: LocalizedError {
    private let message: String

    var errorDescription: String? {
        message
    }

    init(_ message: String) {
        self.message = message
    }
}
  • Related