7

在使用 RestKit 的发布请求期间,我无法将响应映射回对象。

这是代码:

要求:

// mapping for the response. response is an object: {"response":"message","success":bool}
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[GenericResponse class]];
    [responseMapping addAttributeMappingsFromArray:@[@"success",@"response"]];
    responseMapping.setDefaultValueForMissingAttributes = YES;
    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping pathPattern:@"/authenticate" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    // mapping for the request body
    RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
    [requestMapping addAttributeMappingsFromArray:@[@"username", @"password"]];
    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[LoginCriteria class] rootKeyPath:nil];

    // set up the request
    RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://localhost:8080"]];
    [manager addResponseDescriptor:responseDescriptor];
    [manager addRequestDescriptor:requestDescriptor];
    [manager setRequestSerializationMIMEType:@"application/json"];

    // set up the LoginCriteria object
    LoginCriteria* loginCriteria = [LoginCriteria new];
    loginCriteria.password = @"test";
    loginCriteria.username = @"test";

    // make the request
    [manager postObject:loginCriteria path:@"/authenticate" parameters:nil
    success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            GenericResponse *genericResponse = (GenericResponse*)mappingResult;
            NSLog(@"logged in: %@", [mappingResult array]);
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"login failed");
    }];

通用响应.h:

@interface GenericResponse : NSObject
@property (nonatomic) Boolean* success;
@property (nonatomic, copy) NSString* response;
@end

日志:

2012-12-17 15:44:22.890 Radiuus[8221:1703] T restkit.network:RKHTTPRequestOperation.m:139 POST 'http://localhost:8080/authenticate':
request.headers={
    Accept = "application/json";
    "Accept-Language" = "en, fr, de, ja, nl, it, es, pt, pt-PT, da, fi, nb, sv, ko, zh-Hans, zh-Hant, ru, pl, tr, uk, ar, hr, cs, el, he, ro, sk, th, id, ms, en-GB, ca, hu, vi, en-us;q=0.8";
    "Content-Type" = "application/json; charset=utf-8";
    "User-Agent" = "Radiuus/1.0 (iPhone Simulator; iOS 6.0; Scale/1.00)";
}
request.body=(null)
2012-12-17 15:44:23.244 Radiuus[8221:5d0b] T restkit.network:RKHTTPRequestOperation.m:156 POST 'http://localhost:8080/authenticate' (200):
response.headers={
    "Content-Type" = "application/json";
    Date = "Mon, 17 Dec 2012 20:44:23 GMT";
    Server = "Apache-Coyote/1.1";
    "Transfer-Encoding" = Identity;
}
response.body={"response":"authentication succeeded","success":true}
2012-12-17 15:44:23.246 Radiuus[8221:4f03] W restkit.object_mapping:RKMapperOperation.m:76 Adding mapping error: Expected an object mapping for class of type 'LoginCriteria', provider returned one for 'GenericResponse'

从日志中,对我来说奇怪的是,RestKit 似乎期望反序列化对 LoginCriteria 对象的响应,但是当它正确获取 GenericResponse 对象时“失败”,这当然是正确的。

任何帮助是极大的赞赏!

4

3 回答 3

9

感谢您对您的问题的回答,因为它引导我朝着正确的方向弄清楚如何使用 RestKit 的内置方法之一来解决这个问题,而不是修改核心代码。

从他的文档https://github.com/RestKit/RestKit/wiki/Object-mapping处理核心数据发布/放置中的多个根对象部分中,他提到如果您想发布一种类型的对象,但是在响应中收到另一个,那么您必须在请求操作中nil退出。targetObject他的文档中缺少一个完整的示例,所以这是我使用的代码块:

RKManagedObjectRequestOperation *operation = [RKObjectManager.sharedManager appropriateObjectRequestOperationWithObject: objectToBePOSTed method:RKRequestMethodPOST path: path parameters: params];
operation.targetObject = nil;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    //handle success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    //handle failure
}];
[RKObjectManager.sharedManager enqueueObjectRequestOperation:operation];

~ 节日快乐

于 2012-12-25T19:51:29.177 回答
0

我对 RestKit 有同样的问题。解决方案是为我作为响应发布的对象添加映射。

于 2012-12-18T13:34:33.107 回答
0

我深入研究了 RestKit 代码,并在mapObject函数中找到了以下代码段RKMapperOperation.m

if (NO == [[self.targetObject class] isSubclassOfClass:objectMapping.objectClass]) {
            if ([_mappingsDictionary count] == 1) {
                NSString *errorMessage = [NSString stringWithFormat:
                                          @"Expected an object mapping for class of type '%@', provider returned one for '%@'",
                                          NSStringFromClass([self.targetObject class]), NSStringFromClass(objectMapping.objectClass)];
                [self addErrorWithCode:RKMappingErrorTypeMismatch message:errorMessage keyPath:keyPath userInfo:nil];
                return nil;
            } else {
                // There is more than one mapping present. We are likely mapping secondary key paths to new objects
                destinationObject = [self objectWithMapping:mapping andData:mappableObject];
            }
        }

第一条if语句检查以确保targetObject(请求对象)具有位于objectMapping.objectClass(响应对象)层次结构中的类类型。由于我的请求和响应对象不同,这当然会失败。我在该行设置了一个断点来证明这一点。这是我检查时打印的内容:

(lldb) po self.targetObject
(id) $1 = 0x09fb54d0 <LoginCriteria: 0x9fb54d0>
(lldb) po objectMapping.objectClass
(Class) $2 = 0x00162c58 GenericResponse

如您所见,它们属于不同的类型,因此如果成功并且函数返回 nil,则返回未映射的响应。我只是替换return nil;destinationObject = [self objectWithMapping:mapping andData:mappableObject];,一切都按预期工作。

我对这个解决方案不满意,因为我不觉得 RestKit 的作者打算让帖子发送和接收不同的对象。因此,这是一个黑客。在 a) 我听到更好的解决方案,或者 b) RestKit 的作者自己做出这个改变(或接受我的 :) 之前,我不会回答这个问题。

于 2012-12-18T18:46:20.400 回答