Nissaba
Nissaba

Reputation: 973

Swift 5 CoreData predicate using UUID

I have an entity for which I set some ID as UUID object. And I have this function to check if it is already recorded in the persistent store.

I had found some forme of example that did not work as the example was using some 'NSPredicate(format: "%K == %@", #KeyPath(attribute), id)' code that does not work in swift.

So I am trying to figure out how I go about this in swift. I would prefer not to store the UUID as a simple string since coreData lets us save UUID object.

I have this method but it is crashing on the NSPredicate line:

static func isKnownBikeID(_ bleID: UUID) -> Bool {
    let context = A18DataStore.shared.viewContext
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Bike")
    fetchRequest.predicate = NSPredicate(format: "%K == %@", [\Bike.bleID , bleID] as CVarArg)
    do{
        let bikes = try context.fetch(fetchRequest)
        return bikes.count > 0
    }
    catch let error as NSError {
        print("Could not fetch. \(error), \(error.userInfo)")
    }
    return false
}

Edit: I get en exception with my curent method:

2021-07-16 11:55:28.390629-0400 A18 UAT[9260:4171027] -[Swift.__SwiftDeferredNSArray rangeOfString:]: unrecognized selector sent to instance 0x282c22cc0

Upvotes: 8

Views: 2773

Answers (2)

Martin R
Martin R

Reputation: 540005

  • The %K format expects a key path string, this can be obtained using the #keyPath directive.
  • The %@ format expects an Objective-C object, here we can use the toll-free bridging between UUID and NSUUID.

That gives:

let predicate = NSPredicate(format: "%K == %@",
                            #keyPath(Bike.bleID), bleID as NSUUID)

Upvotes: 18

Nissaba
Nissaba

Reputation: 973

With a bit of help from @Larme

static func isKnownBikeID(_ bleID: UUID) -> Bool {
        let context = A18DataStore.shared.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Bike")
        fetchRequest.predicate = NSPredicate(format: "%K == %@", "bleID" , bleID as CVarArg)

        do{
            let bikes = try context.fetch(fetchRequest)
            return bikes.count > 0
        }
        catch let error as NSError {
            print("Could not fetch. \(error), \(error.userInfo)")
        }
        return false
    }

This said @vadian is right.

The example I had was asking to do some manipulation on a key path, so I initially understood I HAD to use some .bleID thing to get it to work and yes just using the name of the field works.

Upvotes: 2

Related Questions