为RestKit创建一个包装器

时间:2012-07-25 08:50:53

标签: ios objective-c restkit objective-c-blocks grand-central-dispatch

我正在尝试为RestKit编写一个包装器,以便所有请求都调用一个函数,而这个函数又会通过RestKit触发请求。

这是我到目前为止所拥有的:

一个函数会调用我的包装器,如下所示:

NSDictionary * response = [Wrappers sendRequestWithURLString:url method:@“GET”];

我的包装方法:

+ (NSDictionary *)sendRequestWithURLString:(NSString *)request method:(NSString *)method
{    
    RKRequestDidFailLoadWithErrorBlock failBlock;

    if ([method isEqualToString:@"GET"])
        return [self sendGETRequestWithURLString:request withFailBlock:failBlock];

    else if ([method isEqualToString:@"POST"])
        return [self sendPOSTRequestWithURLString:request withFailBlock:failBlock];

    return nil;
}




   + (NSDictionary *)sendGETRequestWithURLString:(NSString *)request withFailBlock:(RKRequestDidFailLoadWithErrorBlock)failBlock {

        RKObjectManager *manager = [RKObjectManager sharedManager];

        __block NSDictionary *responseDictionary;

        [manager loadObjectsAtResourcePath:request usingBlock:^(RKObjectLoader *loader) {

            loader.onDidLoadResponse = ^(RKResponse *response) {

                [self fireErrorBlock:failBlock onErrorInResponse:response];

                RKJSONParserJSONKit *parser = [RKJSONParserJSONKit new]; 
                responseDictionary = [[NSDictionary alloc] initWithDictionary:[parser objectFromString:[response bodyAsString] error:nil]];
            };
        }];

        return responseDictionary;
    }

+ (void)fireErrorBlock:(RKRequestDidFailLoadWithErrorBlock)failBlock onErrorInResponse:(RKResponse *)response {

    if (![response isOK]) {

        id parsedResponse = [response parsedBody:NULL];
        NSString *errorText = nil;

        if ([parsedResponse isKindOfClass:[NSDictionary class]]) {
            errorText = [parsedResponse objectForKey:@"error"];
        }

        if (errorText)
            failBlock([self errorWithMessage:errorText code:[response statusCode]]);
    }
}

+ (NSError *)errorWithMessage:(NSString *)errorText code:(NSUInteger)statusCode {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" 
                                                    message:@"Please make sure you are connected to WiFi or 3G." 
                                                   delegate:nil
                                          cancelButtonTitle:@"OK" 
                                          otherButtonTitles:nil];
    [alert show];

    return nil;
}

这里的问题是当responseDictionary返回时,值为nil,因为onDidLoadResponse在并发运行时尚未处理。

在这种情况下,设置responseDictionary的最佳方法是什么?我试图避免调用另一个类的setter方法。在这种情况下,我唯一的选择是使用委托,这会破坏创建包装类的整个目的,因为RestKit调用需要使用委托方法来返回响应吗?

我是否能够通过我的包装器success块来更新一些本地的ivar?我该怎么做?

1 个答案:

答案 0 :(得分:0)

如你所说,你通过了一个成功的阻止。以下是如何执行此操作的示例:

·H

typedef void (^kServiceCompleteBlock)(NSDictionary* responseDictionary);

...
+ (NSDictionary *)sendGETRequestWithURLString:(NSString *)request withFailBlock:(RKRequestDidFailLoadWithErrorBlock)failBlock completion: (kServiceCompleteBlock) completion ;

...

.m

+ (NSDictionary *)sendGETRequestWithURLString:(NSString *)request withFailBlock:(RKRequestDidFailLoadWithErrorBlock)failBlock completion: (kServiceCompleteBlock) completion {

...

loader.onDidLoadResponse = ^(RKResponse *response) {

            [self fireErrorBlock:failBlock onErrorInResponse:response];

            RKJSONParserJSONKit *parser = [RKJSONParserJSONKit new]; 
            responseDictionary = [[NSDictionary alloc] initWithDictionary:[parser objectFromString:[response bodyAsString] error:nil]];

            if( completion )
               completion(responseDictionary);
        };

...

} 

但是,让我警告你一个潜在的设计缺陷。您应该设计应用程序,以便UI由您的数据驱动,而不是您的Web服务。这意味着您的UI应在数据模型更新时自动更新,而不是在Web服务返回时更新。请注意如何使用此响应字典。如果要更新用户界面,那么你就是在危险的道路上奔跑。