Search code examples
iosobjective-cios6restkit

Using addConnectionForRelationship for an array of IDs


I am receiving the following response from my REST Server.

{
    id: 1,
    model_id: 1,
    plant_id: 1,
    users: [
       2,
       9
    ]
}

To which I am trying to map the following model:

@property (nonatomic, retain) Model *model; 
@property (nonatomic, retain) Plant *plant; 
@property (nonatomic, retain) NSSet *expertUsers;

and "expertUsers" is a set of objects, based of a class called "User".

Now, I am trying to follow the same approach I have used in the past to connect users to objects, without having the full object. I have been using the following solution, and it works great for single objects.

[pictureMapping addConnectionForRelationship:@"lastModifiedBy" connectedBy:@{ @"lastModifiedByID": @"identifier" }];

However, how can I replicate the same thing, but this time with an array of IDs?

I would need something like this:

[modelExperts addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"users" toKeyPath:@"expertUsers" withMapping:userMapping **addConnectionForRelationship:@"lastModifiedBy" connectedBy:@{ @"lastModifiedByID": @"identifier" }**]];

EDIT #1:

Here is my current Core Data model:

@interface Cell : NSManagedObject
@property (nonatomic, retain) NSNumber *identifier;
@property (nonatomic, retain) NSSet *managers; // To Many Users
@end


@interface User : NSManagedObject
@property (nonatomic, retain) NSNumber *identifier;
@end

RKEntityMapping *cellMapping = [RKEntityMapping mappingForEntityForName:@"Cell" inManagedObjectStore:managedObjectStore];
cellMapping.identificationAttributes = @[@"identifier"];

NSEntityDescription *cellManagersEntityDescription = [NSEntityDescription entityForName:@"Cell" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
NSRelationshipDescription *userManagersRelationshipDescription = [cellManagersEntityDescription relationshipsByName][@"managers"]; // To many relationship for the `User` entity
RKConnectionDescription *cellManagersConnection = [[RKConnectionDescription alloc] initWithRelationship:userManagersRelationshipDescription attributes:@{ @"managers": @"identifier" }];
[cellMapping addConnection:cellManagersConnection];

Here is my Rest JSON answer for Cell:

{
id: 1,
managersIDs: [
2
],}

However, I keep getting the following:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot connect relationship: invalid attributes given for source entity 'Cell': managers'
*** First throw call stack:
(
0   CoreFoundation                      0x03c646f4 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x02df38b6 objc_exception_throw + 44
2   CoreFoundation                      0x03c64558 +[NSException raise:format:arguments:] + 136
3   Foundation                          0x029d45ee -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4   Poka                                0x001db61f -[RKConnectionDescription initWithRelationship:attributes:] + 1279
5   Poka                                0x0000bdf3 -[APIConnector setupMapping] + 12451
6   Poka                                0x000089ef -[APIConnector init] + 159
7   Poka                                0x001863da -[IJContext createClassInstanceFromRegistration:withProperties:] + 186
8   Poka                                0x00184f12 -[IJContext instantiateClass:withProperties:] + 594
9   Poka                                0x00186de0 +[NSObject(Injective) injectiveInstantiate] + 96
10  Poka                                0x00008275 -[PokaAppDelegate application:didFinishLaunchingWithOptions:] + 309
11  UIKit                               0x01b65525 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 309
12  UIKit                               0x01b65d65 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1536
13  UIKit                               0x01b6a578 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
14  UIKit                               0x01b7e57c -[UIApplication handleEvent:withNewEvent:] + 3447
15  UIKit                               0x01b7eae9 -[UIApplication sendEvent:] + 85
16  UIKit                               0x01b6c1f5 _UIApplicationHandleEvent + 736
17  GraphicsServices                    0x048bc33b _PurpleEventCallback + 776
18  GraphicsServices                    0x048bbe46 PurpleEventCallback + 46
19  CoreFoundation                      0x03bdfe95 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
20  CoreFoundation                      0x03bdfbcb __CFRunLoopDoSource1 + 523
21  CoreFoundation                      0x03c0a8ac __CFRunLoopRun + 2156
22  CoreFoundation                      0x03c09bf3 CFRunLoopRunSpecific + 467
23  CoreFoundation                      0x03c09a0b CFRunLoopRunInMode + 123
24  UIKit                               0x01b69cad -[UIApplication _run] + 840
25  UIKit                               0x01b6bf0b UIApplicationMain + 1225
26  Poka                                0x0000810d main + 141
27  libdyld.dylib                       0x032db725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Solution

  • The class you're looking for is RKConnectionDescription. The code would look something like:

    NSEntityDescription *pictureEntity = [NSEntityDescription entityForName:@"Picture" inManagedObjectContext:managedObjectContext];
    NSRelationshipDescription *expertUsers = [pictureEntity relationshipsByName][@"expertUsers"]; // To many relationship for the `User` entity
    RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:expertUsers attributes:@{ @"users": @"userID" }];
    

    Assuming that your entities are Picture and User and that the User entity has an identity attribute named userID and the Picture entity has an NSArray or NSSet attribute that is named users and contains the identities mapped from users in the JSON.

    Then you can add the connection to your pictureMapping.


    In your new code, this line is wrong:

    RKConnectionDescription *cellManagersConnection = [[RKConnectionDescription alloc] initWithRelationship:userManagersRelationshipDescription attributes:@{ @"managers": @"identifier" }];
    

    Because it is using the managers attribute which holds the entity instances. It should be linking to an attribute that you don't have which holds the identities of the manager entity instances that you want to link to. So:

    1. Add an attribute managerIds
    2. Add a mapping to fill managerIds with the ids from the JSON
    3. Update cellManagersConnection to reference managers