6

我已经使用 RestKit 0.10.0 一段时间了,到目前为止,我只将序列化对象发布到我的服务器:

[[RKObjectManager sharedManager] postObject:serializedObject
                                 usingBlock:^(RKObjectLoader *loader) {
                                     loader.delegate = self;
                                     loader.objectMapping = responseMapping;
                                     loader.serializationMIMEType = RKMIMETypeFormURLEncoded;
                                     loader.targetObject = nil;
                                 }];

到现在为止还挺好。但我现在需要使用一些查询参数向服务器发出 GET 请求。想到的第一件自然的事情就是和我发布对象一样:

  • 为封装查询参数的对象创建序列化映射
  • 为从服务器接收的对象创建响应映射
  • 为 RKRequestMethodGET 定义和使用路由器(而不是 RKRequestMethodPOST)
  • 使用 getObject:usingBlock(而不是 postObject:usingBlock)发出请求

我很快发现这不是这样做的方法,因此在搜索了可用资源(RestKit WikiRestKit Google 组)之后,我现在知道两种被认为是有效的解决方案:

  • 将查询参数附加到资源路径。

这完美地工作。

NSDictionary *queryParams = [NSDictionary dictionaryWithObjectsAndKeys:
                                          token, @"accessToken",
                                          [NSNumber numberWithInt:level], @"level",
                                          [NSNumber numberWithInt:count], @"count",
                                          nil];

NSString* resourcePath = [PEER_SUGGESTIONS_CONTROLLER_PATH stringByAppendingQueryParameters:queryParams];

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:resourcePath
                                                usingBlock:^(RKObjectLoader *loader) {
                                                    loader.delegate = self;
                                                    loader.objectMapping = responseMapping;
                                                }];
  • 在加载程序块中设置查询参数。

这不会发送查询参数。

RKParams *params = [RKParams params];
[params setValue:token forParam:@"accessToken"];
[params setValue:[NSNumber numberWithInt:level] forParam:@"level"];
[params setValue:[NSNumber numberWithInt:count] forParam:@"count"];

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:PEER_SUGGESTIONS_CONTROLLER_PATH
                                                usingBlock:^(RKObjectLoader *loader) {
                                                    loader.delegate = self;
                                                    loader.objectMapping = responseMapping;
                                                    loader.params = params;
                                                }];

我的问题是:

  1. 为什么第二种解决方案不起作用?
  2. 为什么第一个解决方案无需将 loader.targetObject 设置为 nil 就可以工作,尽管我在 JSON 响应中没有任何根键路径?
  3. 在什么情况下我应该使用 getObject:usingBlock 方法?它的预期目的是什么?
  4. 我应该使用 loader.params 做什么?wiki中的对象映射教程说此属性可用于封装 POST 参数,但我看不到重点,因为我可以将参数包装在使用 postObject:usingBlock 方法发送的序列化对象中。

谢谢。

[稍后编辑]

关于我的第二个问题的答案:在发出 POST 请求时,我一直在加载程序块中将 targetObject 设置为 nil,因为否则 RestKit 将尝试使用发送对象映射作为响应(查看此链接以获取相关讨论)。但是由于我使用的是 loadObjectsAtResourcePath:usingBlock:,所以没有对象被发送,因此响应自然会映射到响应映射上,而不必将 targetObject 设置为 nil。

4

2 回答 2

4
  1. 为什么第二种解决方案不起作用?

params 用于创建 HTTP 正文,在 GET/HEAD 请求中不使用该正文。

  1. 为什么第一个解决方案无需将 loader.targetObject 设置为 nil 就可以工作,尽管我在 JSON 响应中没有任何根键路径?

我认为 targetObject 默认为 nil 。您通常不设置它,如果需要,请求将创建它。我唯一一次使用它是在请求没有主键或其他奇怪问题的对象时。

  1. 在什么情况下我应该使用 getObject:usingBlock 方法?它的预期目的是什么?

这是一种方便的方法,因此您不必记住所有正确的语法。在内部,它只是使用 GET 发送一个对象加载请求。

编辑:

如果您有要更新的对象,请使用此选项。

  1. 我应该使用 loader.params 做什么?来自 wiki 的对象映射教程说这个属性可以用来封装 POST 参数,但我看不到重点,因为我可以将参数包装在使用 postObject:usingBlock 方法发送的序列化对象中。

无论您在 params 中输入什么,都将被序列化为 HTTP 正文(或正文流)。同样, postObject:usingBlock: 只是一种方便的方法,因此您不必记住所有内容。

RestKit 是开源的。如果您不确定它是如何工作的,您可以在内部自由地遵循参数。如果您的应用程序和 Web 服务设计良好,您应该能够使用便捷的方法。有时你不能,然后你可以像以前那样使用原始表单。

编辑:Q Hrm,引用你的要点弄乱了数字......

于 2012-06-27T20:16:22.760 回答
3

我解决了向 RKObjectLoader 添加一个类别,即:

对于方法

-(void)getObject:(id<NSObject>)object usingBlock:(RKObjectLoaderBlock)block;

我在 Category 中添加了一个修改后的方法:

-(void)getObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters usingBlock:(void(^)(RKObjectLoader *))block;

这是列表 fpr 文件“RKObjectManager+QueryParameters”:

//
//  RKObjectManager+QueryParameters.h
//  AlphaClient
//
//  Created by Antonio Rossi on 14/07/12.
//

#import <RestKit/RestKit.h>

@interface RKObjectManager (QueryParameters)

- (void)getObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters usingBlock:(void(^)(RKObjectLoader *))block;
- (void)sendObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters method:(RKRequestMethod)method usingBlock:(void(^)(RKObjectLoader *))block;

@end

这是文件“RKObjectManager+QueryParameters.m”的列表:

//
//  RKObjectManager+QueryParameters.m
//  AlphaClient
//
//  Created by Antonio Rossi on 14/07/12.
//

#import "RKObjectManager+QueryParameters.h"

@implementation RKObjectManager (QueryParameters)

- (void)getObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters usingBlock:(void(^)(RKObjectLoader *loader))block {
    [self sendObject:object queryParameters:queryParameters method:RKRequestMethodGET usingBlock:block];
}

- (void)sendObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters method:(RKRequestMethod)method usingBlock:(void(^)(RKObjectLoader *))block {
    NSString *resourcePath = [self.router resourcePathForObject:object method:method];
    [self sendObject:object toResourcePath:resourcePath usingBlock:^(RKObjectLoader *loader) {
        loader.method = method;

        // need to transform the original URL because when method is GET the additional paramentes don't get added
        RKURL *originalBaseURL = [RKURL URLWithBaseURL:[loader.URL baseURL]];
        NSString *resourcePath = [self.router resourcePathForObject:object method:RKRequestMethodGET];
        RKURL *authTokenURL = [originalBaseURL URLByAppendingResourcePath:resourcePath queryParameters:queryParameters];
        [loader setURL:authTokenURL];

        block(loader);
    }];
}

@end

另一个步骤是添加#import "RKObjectManager+QueryParameters.h"您的实现文件。在这个新方法中,假设routerRKObjectManager 的属性在调用它之前已经定义好了。

于 2012-07-14T13:31:50.310 回答