Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
293 views
in Technique[技术] by (71.8m points)

core data - RESTKit: Duplicate Objects in relationship after POST

Below is my setup:

- (RKManagedObjectStore *)setupCoreDataWithRESTKit
{
    NSError * error;
    NSURL * modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"App" ofType:@"momd"]];
    NSManagedObjectModel * managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
    self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

    [self.managedObjectStore createPersistentStoreCoordinator];

    NSArray * searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString * documentPath = [searchPaths objectAtIndex:0];
    NSPersistentStore * persistentStore = [self.managedObjectStore addSQLitePersistentStoreAtPath:[NSString stringWithFormat:@"%@/App%@.sqlite", documentPath, [TBSPersistence username]] fromSeedDatabaseAtPath:nil withConfiguration:nil options:[self optionsForSqliteStore] error:&error];
    NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);

    NSLog(@"Path: %@", [NSString stringWithFormat:@"%@/App%@.sqlite", documentPath, [TBSPersistence username]]);

    if(!persistentStore){
        NSLog(@"Failed to add persistent store: %@", error);
    }

    [self.managedObjectStore createManagedObjectContexts];

    return self.managedObjectStore;
}

POST Invite -- Invite has a to-many relationship with Activity::

-(void)sendInvite:(NSInteger)methodType
{
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    self.objectManager = [self getObjectManager];
    self.objectManager.managedObjectStore = appDelegate.managedObjectStore;

    RKEntityMapping *invitationMapping = [RKEntityMapping mappingForEntityForName:kInvite
                                                             inManagedObjectStore:self.objectManager.managedObjectStore];



    RKEntityMapping *activityMapping = [RKEntityMapping mappingForEntityForName:kActivity
                                                           inManagedObjectStore:self.objectManager.managedObjectStore];


    Invite *invitation;


            invitationMapping = [RESTMappingProvider invitionPostMapping:invitationMapping];
            invitationMapping.identificationAttributes = @[@"inviteId"];

            activityMapping =  [RESTMappingProvider activityPostMapping:activityMapping];
           activityMapping.identificationAttributes = @[@"activityId"];

            [invitationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:kActivitiesRelationship
                                                                                              toKeyPath:kActivitiesRelationship
                                                                                            withMapping:activityMapping]];
            invitation = [self setupInviteProperties:STPOST];
            [self setupDescriptors:invitationMapping andKeyPath:kKeyPath descriptorClass:0];

            [self.objectManager.HTTPClient  registerHTTPOperationClass:[AFHTTPRequestOperation class]];

            [self.objectManager postObject:invitation path:kKeyPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            } 
            failure:^(RKObjectRequestOperation *operation, NSError *error) {
            }];

        }

     }

Descriptor:

-(void)setupDescriptors:(RKEntityMapping *)invitationMapping andKeyPath:(NSString *)keyPath descriptorClass:(BOOL)isTemplate
{

RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[invitationMapping inverseMapping] objectClass:[Invite class] rootKeyPath:nil method:RKRequestMethodAny];

NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:invitationMapping
                                                                                        method:RKRequestMethodGET
                                                                                   pathPattern:keyPath
                                                                                       keyPath:nil
                                                                                   statusCodes:statusCodeSet];

self.objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[self.objectManager addRequestDescriptor:requestDescriptor];
[self.objectManager addResponseDescriptor:responseDescriptor];

}

I POST just fine. When I get a Response, I get the assigned ID's, for the created objects in the database, back from the server.

POSTING: @"inviteId" : @"0" @"activityId" : @"0"

In response, I get everything back as POSTED, however, the server issues Real IDs.

RESPONSE: @"inviteId" : @"123456" @"activityId" : @"234567"

Problem:

invite Object gets updated with the assigned ID auto-magically; however, the activity objects become duplicates in CoreData (.sqlite) with one of the duplicate will have @"0" as the activityID, while its duplicate will have the assigned Id @"234567"

Later when I GET, only the assigned Id object (@"234567") get updated. Objects with@"0"` Id's are never touched and remain in Core Data.

Question: How can I avoid the duplicate record and why is this not happening to the invite Object

* UPDATE *

Returned JSON:

{
    "inviteId": 226,
    "meetingType": 2,
    "activities": [{
        "locationAddress": "4th Floor",
        "startTime": "2014-05-07T01:15:23Z",
        "activityId": 263,
        "latitude": "0",
        "longitude": "0",
        "meetupId": 226,
        "locationName": "West Conference Room",
        "oldId": -7360
    }, {
        "locationAddress": "123 Main St. ",
        "startTime": "2014-05-06T20:15:45Z",
        "activityId": 264,
        "latitude": "0",
        "longitude": "0",
        "meetupId": 226,
        "locationName": "Starwood Building",
        "oldId": -9325
    }],
    "comment": "Comments",
    "status": 0,
    "senderId": "Userid",
    "startDate": "2014-05-07T13:15:00Z"
}

activities is the name of the relationship between Invite & Activity entities

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is the expected (if perhaps not ideal) outcome - RestKit is only able to map the response onto the sent object (not its relationships).

A good option could be to use fetch request blocks to find and purge the orphan activity objects at a later date (it wouldn't run after the POST, so you would need to manually find and delete if you needed the dead objects removed immediately).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...