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");
    }];

GenericResponse.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 の組み込みメソッドの 1 つを使用してこの問題を解決する方法を理解するための正しい方向に私を導いてくれました。

彼のドキュメンテーションhttps://github.com/RestKit/RestKit/wiki/Object-mappingの「Handling Multiple Root Objects in Core Data Post/Put」セクションで、1 つのタイプのオブジェクトを投稿したいが、応答で別のものを受信した場合は、要求操作でそれを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 コードを調べたところ、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ことを確認します。リクエスト オブジェクトとレスポンス オブジェクトが異なるため、これはもちろん失敗します。それを証明するために、その行にブレークポイントを設定しました。私が検査したときに印刷されるものは次のとおりです。targetObjectobjectMapping.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 に答える
0

RestKitでも同じ問題がありました。解決策は、私が応答として投稿していたオブジェクトのマッピングも追加することでした。

于 2012-12-18T13:34:33.107 に答える