13

我正在测试 RestKit,需要访问不同的 BaseUrl,有时还需要“一次”从不同的地方访问具有相同 baseUrl 的 Web 服务,最后我还需要在同一个控制器中访问具有不同 ressourcePaths 的相同 baseUrl。

在我的应用程序委托中,我像这样设置了 RKObjectManager 单例。

RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:kBaseUrl];
[objectManager registerClass:[EntityClass1 class] forElementNamed:@"element1"];
[objectManager registerClass:[EntityClass2 class] forElementNamed:@"element2"];
.
.
.
etc.

单例方法很容易使用,但是我不知道如何分离不同的 Web 服务调用。

在实现 RKObjectLoaderDelegate 的 MyViewController 中,我将有两个方法:

- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects         {
    //stuff with result
}

- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error {
    //stuff with error    
}

当 MyViewController 使用一个 RKObjectManager 单例通过一个 baseUrl 访问一个 ressourcePath 时,这不会导致任何问题。

如果我以这种方式启动不同的请求:

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:FLICKRPath delegate:self]
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:FOURSQUAREPath delegate:self]

等等,在同一个MyController中,我的问题是FLICKRPath和FOURSQUAREPath当然有不同的baseUrl,但RKObjectManager只有一个?

如果我得到这个工作并且可以有不同的 RKObjectManagers 另一个问题就会出现。委托方法 didLoadObjects 和 didFailWithError 将从两个 RKObjectManagers 接收结果,除了它们的 baseUrls 之外,我看不到任何其他方法来区分它们。在委托方法中将每个返回值与 baseUrl 甚至更糟糕的 ressourcePath 进行比较对我来说根本没有吸引力。

如果我有不同的 RKObjectManagers,我想我可以向它们传递不同的委托并构建专门用于处理来自不同 baseUrls 和 ressourcePaths 的返回值的类。这意味着我必须在 MyController 和 RestKit 之上构建另一个抽象,这看起来也很混乱。

我有一种强烈的感觉,我正在以错误的方式解决这个问题,RestKit 源代码非常令人印象深刻,这表明我正在与框架作斗争。我非常感谢有关该主题的一些最佳实践见解。我已经浏览了所有可以找到但没有看到上述用例的资源和示例。它始终是一个 RKObjectManager、一个 baseUrl 和一个 ressourcePath。

先感谢您。

4

5 回答 5

10

由于还没有公认的答案:使用多个对象管理器非常简单,使用RestKit.

来自Wiki使用多个基本 URL(和多个对象管理器)):

您创建的第一个对象管理器将是默认情况下使用的共享单例 RestKit。但是通过创建额外的对象管理器,您可以根据需要从它们的 BaseURL 中提取,只要确保保留这些新的管理器。

RKObjectManager *flickrManager = 
    [RKObjectManager objectManagerWithBaseURL:flickrBaseUrl]; // <-- shared singleton
RKObjectManager *foursquareManager = 
    [[RKObjectManager objectManagerWithBaseURL:foursquareBaseUrl] retain]; // <-- you must retain every other instance.

根据您的应用程序,您可能希望将第二个对象管理器放在更易于访问的位置,例如 AppDelegate 上的保留属性,以便根据需要轻松从中提取。如果您需要区分来自两个(或更多)对象管理器的结果,只需在 userData 中为查询设置一个标识符。

- (void)someAction(id)sender {
        // .......
        RKObjectLoader* loader = [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/whatever" delegate:self];
        loader.userData = @"foursquare";
        // or do this, if you need a number instead of a string
        loader.userData = [NSNumber numberWithInt:1234];
        // .......
    }

//Then when the delegate comes back you can cast it into a string or number as appropriate:
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
    // .......
    NSString* source = (NSString*) objectLoader.userData;
    // or, if you did the NSNumber instead:
    NSNumber* source = (NSNumber*) objectLoader.userData;
    // .......
}
于 2011-11-07T08:39:06.780 回答
3

API变更:

RKObjectLoader* loader = [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/whatever" delegate:self];

无法在 RestKit v.0.10.3 中编译(loadObjectsAtResourcePath:delegate: 返回 void)。不过,该方法只包装了几行代码,因此您仍然可以访问加载程序,并添加 userData,如下所示:

RKObjectLoader *loader = [[RKObjectManager sharedManager] loaderWithResourcePath:resourcePath];
loader.userData = @"SOMEDATA";
loader.delegate = self;
loader.method = RKRequestMethodGET;
[loader send];

(添加注释以防其他新用户遇到与我相同的问题)。

于 2012-10-23T14:20:10.017 回答
0

顺便说一句,由于 userData 属性也可用于 RKRequest,因此您可以使用相同的方法来加载/识别请求。

例如,一些 post 请求:

RKClient * client = [RKClient sharedClient];
[client post:@"/your-api-path" usingBlock:^(RKRequest *request) {
    request.userData = @"<some-object-you-can-check-in-delegate-callback>";
    request.params = someParamsForRequest;
    request.delegate = <delegate you want to call when request is finished>;
}];
于 2012-08-31T07:31:13.903 回答
0

使用objectLoader怎么样。您将找到映射的对象类型/类objectLoader.objectMapping.objectClass并根据它而不是 url 添加您的条件

-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
    // your condition based on -> objectLoader.objectMapping.objectClass   
}

希望它会有所帮助

于 2012-12-17T12:58:51.473 回答
0

可能的方法是为每个基本 url 引入一个单音

您可以根据需要实例化任意数量的RKObjectManager对象。但是,只有第一个会被共享。调查initWithHTTPClient: 来源

if (nil == sharedManager) {
    [RKObjectManager setSharedManager:self];
}

我们不能使用默认sharedManager方法来定位特定的对象管理器,但我们可以轻松实现自己的单例。这是 Google 地图对象管理器的示例:

@implementation GMObjectManager

+ (GMObjectManager*)sharedManager
{
    static GMObjectManager *manager;  // keep reference
    if (!manager) {
        // init with custom base url
        NSURL *baseUrl = [NSURL URLWithString:kGMBaseUrl];  
        manager = [GMObjectManager managerWithBaseURL:baseUrl];
    }

    return manager;
}

- (id)initWithHTTPClient:(AFHTTPClient *)client
{
    self = [super initWithHTTPClient:client];
    if (self) {
        // additional initialization
    }

    return self;
}

@end

用法:

CGObjectManager *googleMapsManager = [GMObjectManager sharedInstance];
于 2014-02-17T12:00:46.223 回答