Duck
Duck

Reputation: 36003

Fetching objects from core data entity retrieves wrong object

I have this entity class to retrieve an object by its id. If the object is not found, then created one and return.

  static var request:NSFetchRequest<NSFetchRequestResult> {
    let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: String(describing: Self.self))
    request.returnsDistinctResults = true
    request.returnsObjectsAsFaults = true
    return request
  }

 class func readObjectWith(id:String,
                             createIfNotFound:Bool = false,
                             context:NSManagedObjectContext) -> Object? {
    
    // search for the object
    let predicate = NSPredicate(format: "id == \(id)")
    request.predicate = predicate
    
    do {
      guard let result = try context.fetch(request) as? [Object],
            result.count > 0,
            let item = result.first
      else {
        if createIfNotFound == false { return nil }

        print("new item")
        return Object(context: context)
      }
      // item exists, return
      return item
    } catch {
      return nil
    }
  }

I remove all objects from core data. I run this in a loop. Every time the loop iterates, this is called with a different id and createIfNotFound = true. The "new item" part will just run the first time. All other times the first object created will be returned, and that object's id, has nothing to do with the id passed to the method.

why?

Upvotes: 1

Views: 107

Answers (1)

Warren Burton
Warren Burton

Reputation: 17381

Check if you're creating a fetch request per loop. The fetch var is a static property that initialises once. It's a single-shot object and is returning the results of the first time it fired.

You can do this by changing:

static var request:NSFetchRequest<NSFetchRequestResult>

to

static func freshRequest() -> NSFetchRequest<NSFetchRequestResult>

Also you probably want to set the id on the new Patient object before returning it.

let patient =  Patient(context: context)
patient.id = id
return patient

Upvotes: 1

Related Questions