Skip to content

Sequencing issue with core data relationships

blakewatters edited this page Aug 2, 2011 · 2 revisions

As of version 0.9.3, there is a sequencing issue with the Core Data relationship hydration feature. If you are attempting to connect relationships across objects that are created within the same payload, then the relationships may fail to connect due to order dependence. This issue is documented in Github Issue #173.

This issue will be fixed in 0.9.4, but for now you can work around it by adding the following snippet to RKManagedObjectLoader.m:

// Add `NSMutableArray* _managedObjectMappings;` to ivars and init + dealloc
- (void)objectMapper:(RKObjectMapper*)objectMapper didMapFromObject:(id)sourceObject toObject:(id)destinationObject atKeyPath:(NSString*)keyPath usingMapping:(RKObjectMapping*)objectMapping {
    if ([objectMapping isKindOfClass:[RKManagedObjectMapping class]]) {
        [_managedObjectMappings addObject:objectMapping];
    }    
}

- (void)objectMapperDidFinishMapping:(RKObjectMapper*)objectMapper {
    for (RKManagedObjectMapping* objectMapping in _managedObjectMappings) {
        NSDictionary* relationshipsAndPrimaryKeyAttributes = [(RKManagedObjectMapping*)self.objectMapping relationshipsAndPrimaryKeyAttributes];
        for (NSString* relationshipName in relationshipsAndPrimaryKeyAttributes) {
            NSString* primaryKeyAttribute = [relationshipsAndPrimaryKeyAttributes objectForKey:relationshipName];
            RKObjectRelationshipMapping* relationshipMapping = [self.objectMapping mappingForKeyPath:relationshipName];
            id<RKObjectMappingDefinition> mapping = relationshipMapping.mapping;
            if (! [mapping isKindOfClass:[RKObjectMapping class]]) {
                RKLogWarning(@"Can only connect relationships for RKObjectMapping relationships. Found %@: Skipping...", NSStringFromClass([mapping class]));
                continue;
            }
            RKObjectMapping* objectMapping = (RKObjectMapping*)mapping;
            NSAssert(relationshipMapping, @"Unable to find relationship mapping '%@' to connect by primaryKey", relationshipName);
            NSAssert([relationshipMapping isKindOfClass:[RKObjectRelationshipMapping class]], @"Expected mapping for %@ to be a relationship mapping", relationshipName);
            NSAssert([relationshipMapping.mapping isKindOfClass:[RKManagedObjectMapping class]], @"Can only connect RKManagedObjectMapping relationships");
            NSString* primaryKeyAttributeOfRelatedObject = [(RKManagedObjectMapping*)objectMapping primaryKeyAttribute];
            NSAssert(primaryKeyAttributeOfRelatedObject, @"Cannot connect relationship: mapping for %@ has no primary key attribute specified", NSStringFromClass(objectMapping.objectClass));
            id valueOfLocalPrimaryKeyAttribute = [self.targetObject valueForKey:primaryKeyAttribute];
            if (valueOfLocalPrimaryKeyAttribute) {
                id relatedObject = [objectMapping.objectClass findFirstByAttribute:primaryKeyAttributeOfRelatedObject withValue:valueOfLocalPrimaryKeyAttribute];
                [self.targetObject setValue:relatedObject forKey:relationshipName];
            }
        }
    }
}

Clone this wiki locally