swiftcore-data

Swift Core Data fetch request with inconsistent behavior


I'm currently working on Unit Tests and need to check Core Data operations. I have the following Core Data entry in the database:

<EasyFPU.FoodItem: 0x6000021b00f0> (entity: FoodItem; id: 0x6000002a02c0 <x-coredata://55F63A9D-9195-4991-8B24-8A3FF6301B1E/FoodItem/p6>; data: {
    caloriesPer100g = 72;
    carbsPer100g = "10.4";
    category = Product;
    composedFoodItem = nil;
    favorite = 0;
    id = "220458AD-3216-45A2-9FC3-32285A2A36D0";
    ingredients =     (
    );
    name = Alpenzwerg;
    sugarsPer100g = "9.4";
    typicalAmounts =     (
    );
})

I can get this entry by its name, using the following function:

static func getFoodItemByName(name: String) -> FoodItem? {
    let predicate = NSPredicate(format: "name == %@", name)
    let request: NSFetchRequest<FoodItem> = FoodItem.fetchRequest()
    request.predicate = predicate
    if let result = try? CoreDataStack.viewContext.fetch(request) {
        if !result.isEmpty {
            return result[0]
        }
    }
    return nil
}

Works perfectly fine. However, when trying to achieve the same by using the id instead of name, it fails.

static func getFoodItemByID(_ id: String) -> FoodItem? {
    let predicate = NSPredicate(format: "id == %@", id)
    let request: NSFetchRequest<FoodItem> = FoodItem.fetchRequest()
    request.predicate = predicate
    if let result = try? CoreDataStack.viewContext.fetch(request) {
        if !result.isEmpty {
            return result[0]
        }
    }
    return nil
}

The result returned by the fetch request is empty (0 values).

This is my data model:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23231" systemVersion="24A335" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
    <entity name="FoodItem" representedClassName=".FoodItem" syncable="YES">
        <attribute name="caloriesPer100g" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
        <attribute name="carbsPer100g" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
        <attribute name="category" optional="YES" attributeType="String"/>
        <attribute name="favorite" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
        <attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
        <attribute name="name" optional="YES" attributeType="String"/>
        <attribute name="sugarsPer100g" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
        <relationship name="composedFoodItem" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ComposedFoodItem" inverseName="foodItem" inverseEntity="ComposedFoodItem"/>
        <relationship name="ingredients" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Ingredient" inverseName="foodItem" inverseEntity="Ingredient"/>
        <relationship name="typicalAmounts" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="TypicalAmount" inverseName="foodItem" inverseEntity="TypicalAmount"/>
    </entity>
</model>

Any ideas? It's exactly the same code using exactly the same database. Thanks!


Solution

  • Solved! I fetched the wrong data type. The correct implementation of the getFoodItemByID function must be:

    static func getFoodItemByID(id: UUID) -> FoodItem? {
        let predicate = NSPredicate(format: "id == %@", id as CVarArg)
        let request: NSFetchRequest<FoodItem> = FoodItem.fetchRequest()
        request.predicate = predicate
        do {
            let result = try CoreDataStack.viewContext.fetch(request)
            if !result.isEmpty {
                return result[0]
            }
        } catch {
            debugPrint("Error fetching food item: \(error)")
        }
        return nil
    }
    

    Kudos to @JoakimDanielson for the right hint!