RestKit GET查询参数

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 group)后,我现在知道了两种被认为是有效的解决方案:
  • 将查询参数附加到资源路径中。
这个方法完美地解决了问题。
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会尝试使用发送对象映射进行响应(请参阅link相关讨论)。但是由于我正在使用loadObjectsAtResourcePath:usingBlock:,因此没有对象被发送,因此响应自然会映射到响应映射,而不必将targetObject设置为nil。
2个回答

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

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

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

我认为 targetObject 默认情况下是 nil。你通常不需要设置它,如果需要,请求会自动创建它。我只在请求没有主键或其他奇怪问题的对象时使用它。

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

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

编辑:

如果您要更新对象,请使用此功能。

  1. 我应该如何使用 loader.params?维基上的对象映射教程称此属性可用于封装 POST 参数,但我看不出有什么意义,因为我可以在通过 postObject:usingBlock 方法发送的序列化对象中包装参数。

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

RestKit 是开源的。如果您不确定它的工作原理,可以随时内部跟踪参数。如果您的应用程序和 Web 服务设计良好,则应该能够使用方便的方法。有时您无法这样做,然后您可以使用像您所做的那样的原始表单。

编辑:哎呀,引用您的项目符号混乱了编号...


谢谢。关于GET/HEAD请求的解释非常有帮助。 - Damon Aw
谢谢,这澄清了我所有的误解,除了一个。你说getObject:usingBlock:只是一个方便的方法,它只是使用GET发送对象加载请求。这更像是loadObjectsAtResourcePath:usingBlock:的定义。在getObject:usingBlock:的情况下,我必须指定一个对象作为第一个参数,我不明白它是用来做什么的,因为我只是进行GET操作,而不是PUT或POST。 - sebastian.gherman
例如,如果您已经有一个对象,您可以获取最新的数据(更新),或者您可以访问资源路径 - 两种方式都可以实现相同的功能。无论哪种方式更适合/更容易。 - Paul de Lange

3
我解决了将类别添加到RKObjectLoader的问题,即:
对于方法:
-(void)getObject:(id<NSObject>)object usingBlock:(RKObjectLoaderBlock)block;

我在分类中添加了一个修改后的方法:
-(void)getObject:(id<NSObject>)object queryParameters:(NSDictionary*)queryParameters usingBlock:(void(^)(RKObjectLoader *))block;

这是文件 "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"。在调用这个新方法之前,假设已经定义了RKObjectManager的router属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接