0
votes

In my model I have three entities with the following attributes:

HumanTask { idHumanTask, name, outcomes, status, description }

Outcomes { idOutcome, label, paramsOutcome }

ParamsOutcome { value, xPath }

As you can see HumanTask is an entity that has an attribute of type Outcomes which in turn has an attribute of type ParamsOutcome. What I need is to retrieve a HumanTask instance from its idHumanTask. Then I put the code I use:

- (NSDictionary *)findHumanTaskByID:(NSString *)idHumanTask {

    NSArray *requiredFields = [NSArray arrayWithObjects:
                               @"idHumanTask", @"name", @"outcomes", @"status", @"description", nil];

    NSPredicate *queryPredicate = [NSPredicate predicateWithFormat:@"idHumanTask == %@",idHumanTask];

    NSArray *result = [self.entityManager queryEntity: self.entityName
                                            forFields: requiredFields
                                        withPredicate: queryPredicate
                                           andOrderBy: nil
                                            inContext: self.context
                                        andResultType: NSDictionaryResultType];

    return ([result count] > 0 ? [result objectAtIndex:0] : nil);
}


- (NSArray *)queryEntity: (NSString *)entityName
               forFields: (NSArray*)fieldsRequired
           withPredicate: (NSPredicate *)queryPredicate
              andOrderBy: (NSArray*)sortDescriptors
               inContext: (NSManagedObjectContext *)context
           andResultType: (NSFetchRequestResultType)resultType {

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
    [request setResultType:resultType];
    [request setReturnsDistinctResults:YES];

    if (queryPredicate) {
        [request setPredicate:queryPredicate];
    } 

    if (fieldsRequired) {
        request.returnsDistinctResults = YES;
        [request setPropertiesToFetch:fieldsRequired];
    } 

    if (sortDescriptors) {
        [request setSortDescriptors:sortDescriptors];
    } 

    __block NSArray *result = nil;

    void (^doSearch)(void) = ^{

        NSError *error = nil;

        result = [context executeFetchRequest:request error:&error];

        if (error != nil) {

            NSLog(@"Error: %@", [error description]);
        }
    };

    if ([NSThread isMainThread]) {

        doSearch();

    } else {

        [context performBlockAndWait:doSearch];
    }

    return result;
}

Below the error description I see in console:

**

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid to many relationship ((), name outcomes, isOptional 1, isTransient 0, entity HumanTask, renamingIdentifier outcomes, validation predicates ( ), warnings ( ), versionHashModifier (null) userInfo { }, destination entity Outcome, inverseRelationship humanTask, minCount 0, maxCount 0, isOrdered 0, deleteRule 1) passed to setPropertiesToFetch::' * First throw call stack: (0x32b782a3 0x3aa0e97f 0x32918da1 0x32917ce5 0x32980d4f 0x329814d9 0x3ae254b7 0x3ae299f7 0x32971df7 0x329811cb 0x32917f17 0x8048b 0x80379 0x83d21 0x7346d 0x349cb54d 0x349b0313 0x349c77cf 0x34983803 0x3472dd8b 0x3472d929 0x3475c7cf 0x34a2d0e9 0x34a2c2d5 0x34a2b4a7 0x34a2b431 0x34b61309 0x349e9691 0x349e93d5 0x349e8d3b 0x349dfeab 0x349dbaed 0x34a1d1e9 0xa70c7 0x349e0ad9 0x349e0663 0x349d884b 0x34980c39 0x349806cd 0xfdbbb 0x3498011b 0x366745a3 0x366741d3 0x32b4d173 0x32b4d117 0x32b4bf99 0x32abeebd 0x32abed49 0x349d7485 0x349d4301 0x48505 0x48488) libc++abi.dylib: terminate called throwing an exception

**

2

2 Answers

2
votes

From the documentation of setPropertiesToFetch::

The property descriptions may represent attributes, to-one relationships, or expressions.

Your "outcomes" property is a to-many relationship, and therefore cannot be used here.

If you need the related Outcome objects, you have to execute a "simple" fetch request (without NSDictionaryResultType or setPropertiesToFetch). That returns an array of HumanTask objects, from which you can get the related Outcome objects.

0
votes

In your Core Data Managed Object Model, are your entities correctly being set up ?

I mean, Does HumanTask have a one-to-many relationship to Outcomes and Outcomes a one-to-many relationship to ParamsOutcome and the NSManagedObjects are properly configured (best way of configuring them is delete all your NSManagedObject classes for your entities, select the entities in your core data model and press Cmd+N with your entities selected in the model - xcode will automatically create the classes for you) ?

Try first and retrieve a simple batch of objects. You can use this function (I always create a singleton that handles Core Data operations :

+ (NSArray*) fetchEntity: (NSString*) entityName withPredicate: (NSPredicate*) predicate andSortDescriptors: (NSArray*) sortDescriptors inContext:(NSManagedObjectContext *)context
{

    NSEntityDescription* entity = [NSEntityDescription entityForName: entityName inManagedObjectContext:context];
    NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease];
    [request setIncludesPropertyValues:NO];
    [request setEntity: entity];
    if (predicate)
        [request setPredicate: predicate];
    if (sortDescriptors)
        [request setSortDescriptors: sortDescriptors];
    NSArray *resultArray = nil;
    NSError *error;
    resultArray = [context executeFetchRequest: request error:&error];

    if (resultArray == nil)
        resultArray = [NSArray array];
    return resultArray;
}

    NSArray * humanTasks = [CoreData fetchEntity:NSStringFromClass([HumanTask class]) withPredicate:nil andSortDescriptors:nil inContext:yourManagedObjectContext];