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!
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!