Having troubles making inverse relationships work

34 views
Skip to first unread message

Brendan Duddridge

unread,
Jun 9, 2015, 2:57:05 PM6/9/15
to mobile-c...@googlegroups.com
Hi,

Perhaps I'm missing something, but I'm following the example here for creating inverse relationships:


I've got a similar model:

// in interface file of TFForm class

@property (nonatomic, strong) NSArray *fields;

// in implementation file of TFForm class

@dynamic fields;

+ (Class)fieldsItemClass {
 
return [TFField class];
}

+ (NSString *)fieldsInverseRelation {
 
return @"form";
}


Where TFField has a "form" property which is of type TFForm.

When I access a TFForm instance and try to log the "fields" property, I get null back. Should it automatically create a view and a query for that? Or do I have to do it all manually by creating my own view and query?

I see your example has "albums" as a read-only property. Not sure how you would add an album to an artist if the property is read-only though.

Thanks,

Brendan

Brendan Duddridge

unread,
Jun 10, 2015, 9:58:50 PM6/10/15
to mobile-c...@googlegroups.com
Perhaps I'm misunderstanding the purpose of the propertyItemClass or something else with inverse relationships? Is it not supposed to automatically fetch the records in a one-to-many relationship just by traversing the relationship.

For example:

 NSLog(@"fields from form: %@", currentForm.fields);


Should that not print out the array of children on the parent object?

Jens Alfke

unread,
Jun 11, 2015, 12:11:09 AM6/11/15
to mobile-c...@googlegroups.com

On Jun 9, 2015, at 11:57 AM, Brendan Duddridge <bren...@gmail.com> wrote:

When I access a TFForm instance and try to log the "fields" property, I get null back. Should it automatically create a view and a query for that? Or do I have to do it all manually by creating my own view and query?

No, you don’t have to create a view.

Have you got the types for those model classes registered with the ModelFactory?

—Jens

Brendan Duddridge

unread,
Jun 11, 2015, 12:41:53 PM6/11/15
to mobile-c...@googlegroups.com
I do this at the beginning before I query the database, so I think so:

CBLDatabase *database = self.document.couchDatabase;


// Do this once per launch, probably right after opening the database:

CBLModelFactory* factory = database.modelFactory;

[factory registerClass:[TFForm class] forDocumentType: @"TFForm"];

[factory registerClass:[TFField class] forDocumentType: @"TFField"];

[factory registerClass:[TFCategory class] forDocumentType: @"TFCategory"];

[factory registerClass:[TFSearch class] forDocumentType: @"TFSearch"];

[factory registerClass:[TFPickList class] forDocumentType: @"TFPickList"];

[factory registerClass:[TFFormLayout class] forDocumentType: @"TFFormLayout"];

[factory registerClass:[TFFormEntry class] forDocumentType:@"TFFormEntry"];

Jens Alfke

unread,
Jun 11, 2015, 2:10:04 PM6/11/15
to mobile-c...@googlegroups.com
Just as a sanity check: You are using CBL 1.1, right?

If you are, I don’t know why this isn’t working; try turning on “CBLModel” logging and see what messages you get the first time you try to access the ‘fields’ property.

—Jens

Brendan Duddridge

unread,
Jun 11, 2015, 4:13:46 PM6/11/15
to mobile-c...@googlegroups.com
Ok, I've figured out the problem. I am using version 1.1. In fact, I built the latest master from source just after I read your message just to make sure I was.

What I had to do was set my fields property to be @dynamic. I had incorrectly assumed that would embed the fields array document IDs into my TFForm's document, which I didn't want (in order to reduce conflicts during syncing).

So I had it set as an @synthesized property instead. Changing it to @dynamic fixed the problem and it's working great now.

Brendan Duddridge

unread,
Jun 11, 2015, 4:16:46 PM6/11/15
to mobile-c...@googlegroups.com
Further to this topic of inverse relationships, what happens if I sync and get a new TFField object coming in that should be attached to my TFForm object's fields array? Will that just automatically happen? I may need to add an observer on my fields array to fire off any KVO notifications in order to update my UI with the new field(s) from the sync.


On Tuesday, June 9, 2015 at 12:57:05 PM UTC-6, Brendan Duddridge wrote:

Brendan Duddridge

unread,
Jun 11, 2015, 4:19:04 PM6/11/15
to mobile-c...@googlegroups.com
Oh, and are the objects in the array cached at all? Or when I call myForm.fields will a database fetch be done every time? Or should I cache it myself? Or will the array simply be updated automatically if there's new fields coming in from a sync?

Sorry for all the questions. This is great stuff though. I just want to make sure that I'm using it right.

Jens Alfke

unread,
Jun 11, 2015, 5:41:11 PM6/11/15
to mobile-c...@googlegroups.com

On Jun 11, 2015, at 1:13 PM, Brendan Duddridge <bren...@gmail.com> wrote:

What I had to do was set my fields property to be @dynamic. I had incorrectly assumed that would embed the fields array document IDs into my TFForm's document, which I didn't want (in order to reduce conflicts during syncing).

Oh! In the source code in your initial message you showed “@dynamic fields;”. Otherwise I would have said something.

(@dynamic really just tells the compiler that it’s OK to not have an implementation of the property because an accessor will get registered at runtime. So it’s used both for regular persistent document properties, and computed inverse relations.)

—Jens

Jens Alfke

unread,
Jun 11, 2015, 5:43:58 PM6/11/15
to mobile-c...@googlegroups.com

On Jun 11, 2015, at 1:16 PM, Brendan Duddridge <bren...@gmail.com> wrote:

Further to this topic of inverse relationships, what happens if I sync and get a new TFField object coming in that should be attached to my TFForm object's fields array? Will that just automatically happen? I may need to add an observer on my fields array to fire off any KVO notifications in order to update my UI with the new field(s) from the sync.

Sorry, KVO isn’t supported yet for inverse relations. The property is recomputed by querying every time you call the accessor, so it’ll always have the up-to-date value, but there’s nothing that proactively notices that the database has changed and triggers a KVO notification.

—Jens
Reply all
Reply to author
Forward
0 new messages