简体   繁体   中英

Core Data: fetch an NSManagedObject by its properties

I have an object NetworkMember that has no attributes but is defined by its relationships Person, Network, Level and Role. In my app, I've found all the four relationships, but I want to make sure not to double-register my NetworkMember, thus I'd like to search for this NSManagedObject before instantiating it.

How should I write a query that queries for an NSManagedObject just consisting of relationships?

Cheers

Nik

You can write an NSPredicate against relationships just as you would against attributes.

For example:

- (BOOL)isPerson:(Person *)person memberOfNetwork:(Network *)network {
    // assume NetworkMember entity is ivar networkMemberEntity_
    // assume NSManagedObjectContext is ivar context_

    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    [fetch setEntity:networkMemberEntity_];
    [fetch setPredicate:[NSPredicate predicateWithFormat:
        @"(person == %@) AND (networks CONTAINS %@)", person, network]];
    [fetch setFetchLimit:1];

    NSError *error = nil;
    NSInteger count = [context_ countForFetchRequest:fetch error:&error];
    if (count < 0) {
        // always handle errors in real code
        // and never check for errors using "error == nil"
    }

    return count > 0;
}

In the case you present, however, you should strongly consider whether you really need to do this. It sounds like you're trying to model a many-to-many relationship between Person and Network. If you come from a database background you might think you need a join table for this, and make an intermediate entity.

However, Core Data can manage all of that for you; you can create a many-to-many relationship directly between Person and Network and not have to maintain any intermediate entity or table yourself. Just like how you don't have to worry about primary and foreign keys when dealing with relationships in Core Data, the framework deals with that kind of thing for you, letting you work at the object level.

You can use an NSPredicate with key-value paths to refer to the relationships as the predicate to an NSFetchRequest . For example:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntity entityForName:@"NetworkMember" inManagedObjectContext:managedObjectContext];
[request setPredicate:[NSPredicate predicateWithFormat:@"person.name == %@ AND ANY (roles.name == \"Manager\")", name]];
NSInteger count = [managedObjectContext countForFetchRequest:request error:&error];
[request release];
if (error) { /* handle the error */ }
if (count != 0) { /* do something if the member already exists */ }

If all you need is to confirm the existence of a particular object, you can use the method countForRetchRequest:error: to see how many objects would be returned if you execute the fetch request. If you're doing this test a lot, this can be much more efficient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM