views:

2690

answers:

5

Let's say I have two Entity classes: SocialApp and SocialAppType

In SocialApp I have one Attribute: appURL and one Relationship: type.

In SocialAppType I have three Attributes: baseURL, name and favicon.

The destination of the SocialApp relationship type is a single record in SocialAppType.

As an example, for multiple Flickr accounts, there would be a number of SocialApp records, with each record holding a link to a person's account. There would be one SocialAppType record for the "Flickr" type, that all SocialApp records would point to.

When I build an application with this schema, I get a warning that there is no inverse relationship between SocialAppType and SocialApp.

 /Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse

Do I need an inverse, and why?

+7  A: 

In practice, I haven't had any data loss due to not having an inverse - at least that I am aware of. A quick Google suggests you should use them:

An inverse relationship doesn't just make things more tidy, it's actually used by Core Data to maintain data integrity.

-- Cocoa Dev Central

You should typically model relationships in both directions, and specify the inverse relationships appropriately. Core Data uses this information to ensure the consistency of the object graph if a change is made (see “Manipulating Relationships and Object Graph Integrity”). For a discussion of some of the reasons why you might want to not model a relationship in both directions, and some of the problems that might arise if you don’t, see “Unidirectional Relationships.”

-- Core Data Programming Guide

Matthew Schinckel
+1  A: 

The better question is, "is there a reason not to have an inverse"? Core Data is really an object graph management framework, not a persistence framework. In other words, its job is to manage the relationships between objects in the object graph. Inverse relationships make this much easier. For that reason, Core Data expects inverse relationships and is written for that use case. Without them, you will have to manage the object graph consistency yourself. In particular, to-many relationships without an inverse relationship are very likely to be corrupted by Core Data unless you work very hard to keep things working. The cost in terms of disk size for the inverse relationships really is insignificant in comparison to the benefit it gains you.

Barry Wark
A: 

Well, while it might be another problem altogether, I did find a reason not to have an inverse relationship. I have an object graph with circular references, and it appears to mess up object deletions as long as that circular reference was in place. As soon as I deleted an inverse relationship everything worked great. Before that I would get warnings about objects that weren't being deleted.

The (iPhone) application is still in development, but in the past few weeks I haven't had any more trouble with Core Data, other than the warnings it generates about an object not having a inverse relationship.

Again, maybe it was a different problem that just happened to disappear when I deleted the inverse relationship, but on the other hand I had been trying to resolve the problem without removing the inverse relation…

Any thoughts?

Bob Vork
A: 

OK, I'll bite. When creating a to-one relationship, how does one create the inverse? The drop-down only presents one choice: "No inverse relationship." Setting a parent entity in the child doesn't necessarily help things either. Meanwhile, I still get that same compiler warning. (Since I insist to on 0 errors, 0 warnings, I'd really like to find a way back there before continuing!)

True, I can create another to-one relationship heading in the other direction, but I'd have to keep those in sync manually, no? (Or maybe it can be kept in sync for me after all?)

Joe D'Andrea
Nevermind. Silly me. I do *exactly* that - set up a to-one relationship in the other direction, then I can set the inverse. I've set the delete rule to "Nullify" but perhaps it should be cascade (as it is with my to-many relationships)? I do not have many-to-many relationships in this case.
Joe D'Andrea
A: 

I'll paraphrase the definitive answer I found in More iPhone 3 Development by Dave Mark and Jeff LeMarche.

Apple generally recommends that you always create and specify the inverse, even if you don't use the inverse relationship in your app. For this reason, it warns you when you fail to provide an inverse.

Relationships are not required to have an inverse, because there are a few scenarios in which the inverse relationship could hurt performance. For example, suppose the inverse relationship contains an extremely large number of objects. Removing the inverse requires iterating over the set that represents the inverse, weakening performance.

But unless you have a specific reason not to, model the inverse. It helps Core Data ensure data integrity. If you run into performance issues, it's relatively easy to remove the inverse relationship later.

Rose Perrone