Search code examples
swiftcore-dataswiftuiuuid

Fetch Core Data using UUID


How do you fetch an object using its UUID? I have an object (TimeCode) with an id attribute that is of type UUID in the xcdatamodel file. I want to fetch an object of this type from CoreData by using this id attribute in the standard NSPredicate, but I got a compilation error saying that I had to use the id as a CVarArg. But at runtime, when I actually called the function, the program crashed as the ObjectIdentifier type couldn't be cast to CVarArg.

Here is the full code:

func fetchTimeCode(id: ObjectIdentifier) -> TimeCode? {
        var timeCodes = [TimeCode]()
        
        let request: NSFetchRequest<TimeCode> = TimeCode.fetchRequest()
        
        request.predicate = NSPredicate(format: "id ==  %@", id as! CVarArg)
        
        do {
            timeCodes = try self.moc.fetch(request)
        }
        catch let error as NSError {
            print("Error fetching for editing.")
            print(error)
        }
        
        print("fetch request id: \(id)")
        
        return timeCodes.first
    }

Any help would be much appreciated. I looked seemingly everywhere and couldn't find any answers. Right now it seems like the best solution is to just store the id as a string, but that doesn't seem especially elegant. What is the point of having a UUID for your object if you can't easily fetch the object using it?

Update: Here is my code for the TimeCodeViewModel class.

class TimeCodeViewModel: Identifiable {
    var id: ObjectIdentifier
    var fullName = ""
    
    
    init(timeCode: TimeCode) {
        self.id = timeCode.id
        self.fullName = timeCode.fullName!
    }
    
    // class methods
}

Solution

  • In my case it works with a following predicate:

    func getItem(with id: UUID?) -> Item? {
        guard let id = id else { return nil }
        let request = Item.fetchRequest() as NSFetchRequest<Item>
        request.predicate = NSPredicate(format: "%K == %@", "id", id as CVarArg)
        guard let items = try? context.fetch(request) else { return nil }
        return items.first
    }
    

    More importantly, I am using UUID (the same case is in the answer suggested by Martin), not ObjectIdentifier. It is definitely possible to fetch items based on UUID.

    Please try to change a parameter type in your function to UUID