post对象在RestKit postObject方法和RKMappingResult之间的关系是什么? [英] What is the relationship between the post object, in the RestKit postObject method, and the RKMappingResult it returns?

查看:145
本文介绍了post对象在RestKit postObject方法和RKMappingResult之间的关系是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在通过关于RestKit的文档,但我还没有能够解决一些细节在 RKMappingResult

I have been looking through the documentation on RestKit, but I haven't been able to work out some of the specifics on RKMappingResult.

我有代码创建一个 NSManagedObject ,称为 newUser code> mainQueueManagedObjectContext 的RestKit RKManagedObjectStore。然后使用我的对象管理器的 postObject:path:parameters:success:failure:方法将用户发布到服务器。这似乎工作正常。

I have code that creates an NSManagedObject, called newUser, and inserts in the mainQueueManagedObjectContext of the RestKit RKManagedObjectStore. I then use my object manager's postObject:path:parameters:success:failure: method to post the user to the server. This appears to work fine.

当请求完成后,我需要更新 newUser 托管对象上的一些字段,从发布请求的结果。传递到块中的 mappingResult 参数似乎具有正确映射的所有管理对象,其中所有字段都是从服务器的响应中设置的。

I need to update some fields on the newUser managed object when the post request completes, that will not be mapped from the result of the post request. The mappingResult parameter passed into the block seems to have the managed object that is properly mapped with all of the fields set from the response of the server.

显然, mappingResult 中的对象与我发布的对象不是同一个对象,因为它们不在同一个线程中。如果我在发布之前保存 newUser ,它们的 objectID 将在请求完成时返回,映射结果?

Obviously, the object in the mappingResult is not the same object as the one that I posted since they are not in the same thread. If I save newUser before I post, will their objectID's be the same when the request finishes and it returns the mapping result?

我想象 newUser 和映射结果中的对象都指向同一个对象存储在CoreData中,是正确的?我问的原因是,这似乎不是这样的。如果我做一个post请求并保存 newUser 对象和 mappingResult 中返回的对象,我最终得到Core Data中的两个不同的对象,一个用于 newUser ,一个用于映射结果。我通过更改mappingResult对象和 newUser 对象上的字段来确认这一点,并看到它们都独立更改。此外,我下次获取时提取两个用户对象。如何防止这种情况?

I am imagining that both the newUser and the object from the mapping result refer to the same object that is stored in CoreData, is the correct? The reason I ask is that, this appears to not be the case. If I make one post request and save both the newUser object and the object returned in the mappingResult, I end up with two different objects in Core Data, one for the newUser and one for the mapping result. I confirmed this by changing a field on both the mappingResult object and the newUser object and seeing that they were both changed independently. Additionally, fetches two user objects the next time that I fetch. How do I prevent this?

如果这是正确的,如果我崩溃会发生什么请求还没有完成?我不会有一个存根对象只是挂在CoreData?

If, however that is correct, what happens if I crash will the request has not yet completed? Won't I have a stub object just hanging around in CoreData?

如果请求失败,如何删除我创建的存根对象?

If the request fails, how do I delete the stub object that I created? Could I do something like the following, in the failure block?

        dispatch_async(dispatch_get_main_queue(), ^{
            [newUser.managedObjectContext deleteObject:newRegisteredUser];
        });

其中 newUser 我在mainQueue上创建了。

Where newUser, is the managed object that I created on the mainQueue.

最后,如果我通过映射结果在后台线程中找回一个托管对象,我不能将returnedUser设置为用户UI是用来获取信息,因为那是在主线程,所以如何通知UI来更改它的用户?我应该发布通知,告诉UI从核心数据重新获取活动用户吗?

Lastly, if I get back a managed object in a background thread via the mapping result I can't set the returnedUser to be the user that the UI is using to get information from since that is on the main thread, so how do I notify the UI to change it's user? Should I post a notification that tells the UI to refetch the active user from Core Data?

更新重复对象

我已经做了一些进一步的测试,

I have done some further testing and I am definitely getting a duplicate object when the post returns.

我首先创建一个 newUser 并设置属性:

I first create a newUser and set properties on it:

HNGRRegisteredUser *newUser = [NSEntityDescription insertNewObjectForEntityForName:@"RegisteredUser" inManagedObjectContext:context];
newUser.firstName = @"John"
newUser.lastName = @"Smith"
newUser.gender = @"Male"
newUser.email = @"js@email.com"
newUser.hungrosityModel = //fill in all of the attributes for a hungrosityModel, except uniqueID

此时,newUser.uniqueID == nil。然后我保存newUser(我假设我必须这样做RestKit可以使用永久objectID),以创建存根对象。

At this point, newUser.uniqueID == nil. I then save newUser (which I am assuming I have to do so RestKit can use the permanent objectID), to make a stub object.

NSError *saveError;
[newRegisteredUser.managedObjectContext saveToPersistentStore:&saveError];
if (saveError) NSLog(@"Save Error: %@", saveError);
NSLog(@"newUser objectID: %@", [newRegisteredUser.objectID URIRepresentation]);

然后我发布 newUser 对象。 / p>

I then post the newUser object.

[[RKObjectManager sharedManager] postObject:newRegisteredUser path:@"users/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    NSError *saveError;
    HNGRRegisteredUser *returnedUser = [mappingResult firstObject];
    NSLog(@"mappingResult objectID: %@", [returnedUser.objectID URIRepresentation]);

    [returnedUser.managedObjectContext saveToPersistentStore:&saveError];
    if (saveError) NSLog(@"Error saving user upon registration: %@", saveError);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    [newUser.managedObjectContext deleteObject:newUser];
}];

objectID的打印输出如下。

The print outs for the objectIDs are below.

newUser objectID: x-coredata://B74AB613-1060-4D98-ABFC-3B4D89AB12C3/RegisteredUser/p2
mappingResult objectID: x-coredata://B74AB613-1060-4D98-ABFC-3B4D89AB12C3/RegisteredUser/p3

发送到服务器的JSON为:

The JSON that was sent to the server was:

{
    "gender":"Male",
    "lastName":"Smith",
    "firstName":"John",
    "email":"js@email.com",
    "hungrosityModel": {
        "totalNumberOfUpdates":0,
        "peakHungrosity":0.8,
        "hungrosityFractionAtLastUpdate":0,
        "rateOfHungrosification":5e-05,
        "troughHungrosity":0.1,
        "peakUpdates":0
    }
}

从服务器返回的JSON为:

The JSON that was returned from the server was:

{"results": [
    {"receivedFriendRequests": [],
     "firstName": "John",
     "middleName": null,
     "hungrosityModel": {"uniqueID": 13},
     "email": "js@email.com",
     "gender": "Male",
     "lastName": "Smith",
     "sentFriendRequests": [],
     "uniqueID": 14,
     "updatedAt": "2014-03-12T17:45:01.973Z",
     "friends": [],
     "profileImageUpdatedAt": null,
     "createdAt": "2014-03-12T17:45:01.809Z"}
 ]}

对象的响应和请求描述符为:

The response and the request descriptors for the object are:

[[RKObjectManager sharedManager].router.routeSet addRoute:[RKRoute routeWithClass:[HNGRRegisteredUser class] pathPattern:@"users/" method:RKRequestMethodPOST]];

RKResponseDescriptor *registrationResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[HNGRRKMappingProvider registeredUserMapping] method:RKRequestMethodPOST pathPattern:@"users/" keyPath:@"results" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor: registrationResponseDescriptor];

RKRequestDescriptor *registrationRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[[HNGRRKMappingProvider registeredUserMapping] inverseMapping] objectClass:[HNGRRegisteredUser class] rootKeyPath:nil method:RKRequestMethodPOST];
[[RKObjectManager sharedManager] addRequestDescriptor:registrationRequestDescriptor];

用户的映射为:

RKEntityMapping *_mapping = nil;
_mapping = [RKEntityMapping mappingForEntityForName:@"RegisteredUser" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
[_mapping addAttributeMappingsFromArray:@[@"uniqueID",
                                           @"createdAt",
                                           @"updatedAt",
                                           @"firstName",
                                           @"middleName",
                                           @"lastName",
                                           @"email",
                                           @"gender",
                                           @"profileImageUpdatedAt"]];
[_mapping addRelationshipMappingWithSourceKeyPath:@"hungrosityModel" mapping:[HNGRRKMappingProvider basicModelMapping]];
_mapping.identificationAttributes = @[@"uniqueID"];

这是相关的对象映射跟踪:

Here is the relevant object mapping trace:

D restkit.object_mapping:RKMapperOperation.m:377 Executing mapping operation for representation: {
        results =     (
                    {
                createdAt = "2014-03-12T18:22:35.688Z";
                dateOfBirth = "2014-03-12T18:24:02Z";
                firstName = John;
                friends =             (
                );
                gender = Male;
                hungrosityModel =             {
                    uniqueID = 14;
                };
                lastName = Smith;
                middleName = "<null>";
                profileImageUpdatedAt = "<null>";
                receivedFriendRequests =             (
                );
                sentFriendRequests =             (
                );
                uniqueID = 14;
                updatedAt = "2014-03-12T18:22:35.856Z";
            }
        );
    }
     and targetObject: <HNGRRegisteredUser: 0xaa8c180> (entity: RegisteredUser; id: 0xa894550 <x-coredata://44B8DF7A-BDC9-45F2-A137-BFAACF4AAF88/RegisteredUser/p2> ; data: {
        createdAt = nil;
        dateOfBirth = "2014-03-12 18:24:02 +0000";
        email = "js@email.com";
        firstName = John;
        friendRequests = "<relationship fault: 0xa899dd0 'friendRequests'>";
        friends = "<relationship fault: 0xa891ea0 'friends'>";
        gender = Male;
        hungrosityModel = "0xa861980 <x-coredata://44B8DF7A-BDC9-45F2-A137-BFAACF4AAF88/BasicModel/p2>";
        hungrosityUpdateEvents = "<relationship fault: 0xa829d90 'hungrosityUpdateEvents'>";
        isLocalUser = 0;
        lastName = Smith;
        middleName = nil;
        myInvitations = nil;
        profileImageData = nil;
        profileImageThumbnailData = nil;
        profileImageUpdatedAt = nil;
        receivedInvitations = nil;
        registeredUserSettings = nil;
        savedHungrosityComments = "<relationship fault: 0xa8bc450 'savedHungrosityComments'>";
        uniqueID = nil;
        updatedAt = nil;
        user = nil;
        userSettings = nil;
    })
  T restkit.object_mapping:RKMapperOperation.m:320 Examining keyPath 'results' for mappable content...
  D restkit.object_mapping:RKMapperOperation.m:297 Found mappable collection at keyPath 'results': (
            {
            createdAt = "2014-03-12T18:22:35.688Z";
            dateOfBirth = "2014-03-12T18:24:02Z";
            firstName = John;
            friends =         (
            );
            gender = Male;
            hungrosityModel =         {
                uniqueID = 14;
            };
            lastName = Smith;
            middleName = "<null>";
            profileImageUpdatedAt = "<null>";
            receivedFriendRequests =         (
            );
            sentFriendRequests =         (
            );
            uniqueID = 14;
            updatedAt = "2014-03-12T18:22:35.856Z";
        }
    )

 D restkit.object_mapping:RKMappingOperation.m:952 Starting mapping operation...
 T restkit.object_mapping:RKMappingOperation.m:953 Performing mapping operation: <RKMappingOperation 0xa8e4440> for 'HNGRRegisteredUser' object. Mapping values from object {
    createdAt = "2014-03-12T18:22:35.688Z";
    dateOfBirth = "2014-03-12T18:24:02Z";
    firstName = John;
    friends =     (
    );
    gender = Male;
    hungrosityModel =     {
        uniqueID = 14;
    };
    lastName = Smith;
    middleName = "<null>";
    profileImageUpdatedAt = "<null>";
    receivedFriendRequests =     (
    );
    sentFriendRequests =     (
    );
    uniqueID = 14;
    updatedAt = "2014-03-12T18:22:35.856Z";
} to object <HNGRRegisteredUser: 0xa8833b0> (entity: RegisteredUser; id: 0xa8777e0 <x-coredata:///RegisteredUser/t1FD3D8DE-75AD-4194-B157-EB6931B74BDB6> ; data: {
    createdAt = nil;
    dateOfBirth = nil;
    email = nil;
    firstName = nil;
    friendRequests =     (
    );
    friends =     (
    );
    gender = nil;
    hungrosityModel = nil;
    hungrosityUpdateEvents =     (
    );
    isLocalUser = 0;
    lastName = nil;
    middleName = nil;
    myInvitations = nil;
    profileImageData = nil;
    profileImageThumbnailData = nil;
    profileImageUpdatedAt = nil;
    receivedInvitations = nil;
    registeredUserSettings = nil;
    savedHungrosityComments =     (
    );
    uniqueID = 14;
    updatedAt = nil;
    user = nil;
    userSettings = nil;
}) with object mapping (null)

如果有任何更多信息对我们有帮助,请告诉我。

Let me know if there is any more information that would be helpful to know.

推荐答案

是的,对象ID将始终匹配(即使托管对象实例不同,它仍然代表相同的基础实体实例)。

Yes, the object id will always match (even if the managed object instance is different it still represents the same underlying entity instance). Often they will be the same managed object instance as you start on the main thread and RestKit calls you back on the main thread too.

您描述的新实例不会在主线程上启动,而RestKit会在主线程上调用。发生。您发布的原始对象应该直接更新。在你的情况下,不会发生,因为服务器返回一个对象数组。这使RestKit忽略提供的目标对象并创建新的目标对象。在这种情况下,这是一个新的对象,因为数组包含一个项目。要解决这个问题,您将需要修改来自服务器的JSON,因为您不能将映射索引到映射的一部分...

The new instance you describe doesn't happen. The original object you post should be updated directly. In your case that isn't happening because the server is returning an array of objects. This is causing RestKit to ignore the supplied destination object and create new ones. In this case that's one new object because the array contains one item. To fix this you will need to modify the JSON coming from the server as you can't index into the array as part of the mapping...

要删除,您不需要切换线程(虽然你可以,如果你想要未来的打样),这是正确的方法。

To delete, you don't need to switch thread (though you can if you want for future proofing), and that is the correct approach.

你可以发布通知。我通常使用抓取的结果控制器来管理观察您的更改。

You can post a notification. I usually use a fetched results controller as it manages observing changes for you.

这篇关于post对象在RestKit postObject方法和RKMappingResult之间的关系是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆