0

I'm trying to update a relationship in Core Data but am experiencing this issue. I have 2 entities: Trip and GPSLocation. A Trip can have many GPSLocation but a GPSLocation can only be in one Trip, hence an one-to-many relationship from Trip to GPSLocation. I set up my entities in Xcode's model editor like so:

Entity: GPSLocation relationship: trip destination: Trip inverse: gps Type: To one

Entity: Trip relationship: gps destination: GPSLocations inverse: trip Type: To many

Assuming the variable trip is an instance of my Trip entity. In my update routine, I have:

 let request = NSBatchUpdateRequest(entityName: "GPSLocations")
 request.predicate = somePredicate
 request.propertiesToUpdate = ["trip": trip]
 request.resultType = .UpdatedObjectIDsResultType
 do {
   let responses = try managedContext.executeRequest(request) as! NSBatchUpdateResult
   print responses.result!
 } catch let error as NSError {
    print(error)
 }

This code is giving me an NSInvalidArgumentException Reason: 'Invalid relationship' and I'm not sure why. Any help would be very appreciated! Thank you.

EDIT: My predicate is a pretty simple one: NSPredicate(format: "SELF = %@", "1"). I confirmed that record with pk 1 exists via a database visualizer.

EDIT 2: So I did some further testing and noticed something interesting about the 2 routines that I wrote for creating and updating records in entities. Unlike with the update routine, I don't get this invalid relationship problem when I use the create routine. Here is my code for both routines:

// MARK - this routine works fine
func createRecord(entityName: String, fromKeyValue: [String:AnyObject]) -> AnyObject {
  let entityDesc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: managedContext)
  do {
    let entityType = NSClassFromString("myapp." + entityName) as! NSManagedObject.Type
    let entity = entityType.init(entity: entityDesc!, insertIntoManagedObjectContext: managedContext)
    for key in fromKeyValue.keys {
      entity.setValue(fromKeyValue[key], forKey: key)
    }
    try managedContext.save()
    return entity
  } catch let error as NSError {
      return error
  }   

}

// MARK - this one gives me problem..        
func updateRecords(entityName: String, predicate: NSPredicate, keyValue: [String:AnyObject]) -> AnyObject {
  let request = NSBatchUpdateRequest(entityName: entityName)
  request.predicate = predicate
  request.propertiesToUpdate = keyValue
  request.resultType = .UpdatedObjectIDsResultType
  do {
    let responses = try managedContext.executeRequest(request) as! NSBatchUpdateResult
    return responses.result!
  } catch let error as NSError {
    return error
  }
}
7ball
  • 2,183
  • 4
  • 26
  • 61
  • Show your predicate. – sschale May 29 '16 at 07:54
  • Alternatively, see if any of the solutions here help: http://stackoverflow.com/questions/2009399/cryptic-error-from-core-data-nsinvalidargumentexception-reason-referencedata6?rq=1 – sschale May 29 '16 at 08:05
  • I added an edit. Unfortunately I don't think I'm using more than 1 thread, so I doubt that's an issue. – 7ball May 29 '16 at 22:22
  • So I did some more testing I found that my `update` routine is most likely what's causing the problem. I showed my code in EDIT2. If you could take a look that'd be great! – 7ball May 29 '16 at 22:38
  • I think the problem is from your predicate. You are querying entities where attribute `SELF == 1`. Is `SELF` a property of GPSLocation? – Ahmed Onawale May 29 '16 at 22:42
  • I think that's a special attribute. That's apparently how you query by primary key. I printed out the result from the predicate and confirmed that it's not the issue. I believe the issue is in my `updateRecords` routine I shared in **EDIT2**. – 7ball May 29 '16 at 22:44
  • Why are you using `NSBatchUpdateRequest`? That's intended for bulk updates, but your predicate seems to be selecting only one item (if any)to update. – pbasdf May 29 '16 at 23:02
  • Yeah so my predicate here is only used for testing I suppose. The long term goal is to have this work in bulk, but I figure that's kind of out of reach right now, given the fact that I can't even get 1 to update correctly :( – 7ball May 29 '16 at 23:08
  • Unless you know you will have memory problems, I would just fetch all the required `GPSLocations` and set the relationship directly. – pbasdf May 29 '16 at 23:19
  • Yeah that's the route I think I'm going to try next. I think it'll work. Do you happen to know how many rows it will take to cause memory problems? – 7ball May 29 '16 at 23:21
  • It depends on the attributes of your `GPSLocations` and your other memory usage. – pbasdf May 29 '16 at 23:29

0 Answers0