RestKit GET查询参数

时间:2012-06-27 13:23:24

标签: iphone ios get restkit

我一直在使用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方法发送的序列化对象中。
  5. 感谢。

    [LATER EDIT]

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

2 个答案:

答案 0 :(得分:4)

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

params用于创建HTTP主体,该主体未在GET / HEAD请求中使用。

  
      
  1. 为什么第一个解决方案在不必将loader.targetObject设置为nil的情况下工作,尽管我没有任何根密钥路径   在JSON响应中?
  2.   

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

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

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

编辑:

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

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

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

RestKit是开源的。如果您不确定它是如何工作的,您可以在内部自由地遵循这些参数。如果您的应用和Web服务设计得很好,您应该能够使用便捷方法。有时你不能,然后你可以使用像你所做的原始表格。

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

答案 1 :(得分:3)

我解决了将一个Category添加到RKObjectLoader,即:

方法

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

我在类别中添加了一个修改过的方法:

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