一次有多个RKObjectManager(RestKit)

我正在testingRestKit,需要访问不同的BaseUrls,有时也会从不同的地方一次访问同一个baseUrl的Web服务,最后我还需要在同一个控制器中访问同一个baseUrl,并使用不同的资源path。

在我的应用程序委托中,我像这样设置了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的资源path时,这不会造成任何问题。

如果我以这种方式开始不同的请求:

 [[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,我想我可以通过他们不同的委托,并build立专门处理来自不同baseUrls和ressourcePaths返回值的类。 这意味着我必须在MyController和RestKit之上构build另一个抽象,这似乎也很麻烦。

我有一种强烈的感觉,我正在用错误的方式去解决这个问题,RestKit源代码非常令人印象深刻,这表明我是在和框架进行对抗。 我真的很感激有关这个问题的最佳实践见解。 我已经经历了所有可以find的资源和例子,但没有看到上述用例。 它总是一个RKObjectManager,一个baseUrl和一个ressourcePath。

先谢谢你。

因为还没有被接受的答案:使用RestKit使用多个对象pipe理器是非常简单的。

从Wiki ( 使用多个基本URL(和多个对象pipe理器 )):

您创build的第一个对象pipe理器将默认使用共享的单例RestKit。 但是通过创build额外的对象pipe理器,您可以根据需要从BaseURL中取出,只要确保保留这些新的pipe理器即可。

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

根据您的应用程序,您可能希望将第二个对象pipe理器放置在更易于访问的位置,如AppDelegate上的保留属性,以便根据需要轻松取出。 如果您需要区分两个(或更多)对象pipe理器的结果,只需在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; // ....... } 

API更改:

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

不会在RestKit v.0.10.3(loadObjectsAtResourcePath:delegate:returns void)中编译。 这个方法只是包装了几行代码,所以你仍然可以得到加载器,并添加userData,如下所示:

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

(添加注意事项,以防其他新用户遇到同样的问题,我做了)。

另外,由于RKRequest上的userData属性也是可用的,所以您可以使用相同的方法来加载/识别请求。

例如,一些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>; }]; 

如何使用objectLoader。 你会发现映射的对象types/类objectLoader.objectMapping.objectClass并添加你的条件而不是url

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

希望它会有所帮助

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

您可以根据需要实例化多个RKObjectManager对象。 但是,只有第一个会被分享。 查看initWithHTTPClient: 来源 。

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

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

 @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];