Relationship is initialized with boolean value

I have an iOS app written in Swift 2, compiled using Xcode 7.1.1, using Core Data.


One of the entities in my model seems to be initialized with the wrong type of values, and I am out of ideas on how to diagnose and fix the problem.


Even though my app is using a multi-context Core Data stack, I am able to reproduce the problem with a vanilla Core Data stack (code generated by the Xcode template), using this code in my main view controller's viewDidAppear method:


let moc = self.managedObjectContext // Vanilla context from Xcode's Core Data template
let e = NSEntityDescription.insertNewObjectForEntityForName("TaskDefinition", inManagedObjectContext: moc)

for (name, _) in e.entity.relationshipsByName
{
    print(name)
    print(e.valueForKey(name))
}


Here's the console output:


owner
nil
sharedSlave
Optional(0)
schoolYearConfiguration
nil
attachments
2015-12-07 13:35:04.869 Studyo Beta[43113:15618215] -[__NSCFBoolean objectID]: unrecognized selector sent to instance 0x104b51248


There are 2 things to note from this log:


  1. Line 4: The sharedSlave relationship is displayed as an Optional(0) value instead of nil, as are the other relationships
  2. Line 8: Trying to access the attachments relationship raises an exception that seem to indicate that the value is typed as a boolean instead of an object


I have tried running the same code with all my other Core Data entities and it works perfectly fine. The only entity causing me troubles is this one.


I have created a new app from scratch using Xcode's Core Data Single View template, copied my xcdatamodeld file over to the blank app, and the above code runs perfectly fine with all entities.


So I conclude that there is something in my app that introduces this corruption, but after 2 days of pulling my hair out I am out of ideas on what to do to pinpoint the source of corruption.


I tried:


  • Commenting out my class extension that was adding a few methods to the TaskDefinition class
  • Reverting to a plain Core Data Stack


If I remove the sharedMaster and sharedSlave relationships from the model, it works. But I have used one-to-one "self" relationships in other Core Data models without any issues, and it works in a blank app so I can't figure out why those relationships would be problematic.


Again, since I am unable to reproduce the problem in a dummy app it has to be something in my app, but what? I commented out my class extension that was adding a few methods to the TaskDefinition entity, I reverted to a plain Core Data stack...


If any of you has anything to suggest in terms of things to try to diagnose the source of the corruption, I'm all ears!


Thanks,


Pascal

Accepted Reply

Found it: I had 2 readonly boolean properties defined in a Swift class extension for TaskDefinition, whose names were isSharedMaster and isSharedSlave. Looks like whenever the sharedMaster and sharedSlave relationships were accessed via KVO (including fetch requests), the getters of my custom properties were being invoked.


Renaming the properties fixed the problem.

Replies

Nope, you're misunderstanding the error message being displayed.

[__NSCFBoolean objectID]

is not an indication that the object 0x104b51248 is of type NSCFBoolean, it's just the random coincidence that first class the runtime found with an objectID selector was NSCFBoolean.


If you suspect corruption of your database, you're pretty much going to have to look at the actual sqlite database to prove anything.

That, and you'd be much better off iterating through the NSEntityDescription object for the entity and printing out what CoreData thinks the definition is.

I don't suspect corruption of the SQL database, as I am observing the issue with a blank database, where the TaskDefinition entity is the only inserted entity at the time I am printing its description.


I have removed the attachments relationship from my model (that was the one causing the objectId exception), and now all I'm seeing is the sharedMaster and sharedSlave relationships being printed as Optional(0) instead of nil.


I should have mentionned that this is just an observation of a discrepancy that might be the cause of my actual problem, which is:


I my app, I perform a fetch request on TaskDefinition with the following predicate: sharedMaster.foo == someValue.


That fetch request raises this exception: this class is not key value coding-compliant for the key foo.


The fact that I am seeing sharedMaster as being reported as Optional(0) instead of nil gives me a clue that there might be something wrong with my model.


To summarize:


  • I have a fetch request with a predicate on a nil relationship (sharedMaster.foo = someValue)
  • This request raises this class is not key value coding-compliant for the key foo
  • When I print the valueForKeyPath of sharedMaster, I see Optional(0) instead of nil
  • All other relationships on that object are properly reported as nil
  • I can reproduce this with a vanilla core data stack, on an empty database in which a single TaskDefinition entity was inserted
  • I cannot reproduce this in a blank app using the same xcdatamodeld file: all relationships are reported as nil, and my fetch request does not raise an exception.

Renaming the sharedMaster and sharedSlave relationships fixed all my problems.


But why?

Found it: I had 2 readonly boolean properties defined in a Swift class extension for TaskDefinition, whose names were isSharedMaster and isSharedSlave. Looks like whenever the sharedMaster and sharedSlave relationships were accessed via KVO (including fetch requests), the getters of my custom properties were being invoked.


Renaming the properties fixed the problem.