我正在测试RestKit并且需要访问不同的BaseUrls并且有时也“同时”从不同的地方访问具有相同baseUrl的web服务,最后我还需要在同一个控制器中访问具有不同ressourcePath的相同baseUrl。
在我的app委托中,我设置了像这样的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。
提前谢谢。
答案 0 :(得分:10)
由于还没有接受答案:使用RestKit
使用多个对象管理器非常简单。
来自Wiki(Using Multiple Base URLs (and Multiple Object Managers):
您创建的第一个对象管理器将是共享单例 RestKit默认使用。但是通过创建其他对象管理器, 你可以根据需要从他们的BaseURLs拉出来,一定要保留 这些新经理。
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;
// .......
}
答案 1 :(得分:3)
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];
(如果其他新用户遇到与我相同的问题,请添加备注。)
答案 2 :(得分:0)
顺便说一下,由于在RKRequest上也可以使用userData属性,因此您可以使用相同的方法来加载/识别请求。
例如,一些帖子请求:
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>;
}];
答案 3 :(得分:0)
如何使用objectLoader。
您将找到映射的对象类型/类objectLoader.objectMapping.objectClass
,并根据它而不是网址添加条件
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
// your condition based on -> objectLoader.objectMapping.objectClass
}
希望它会有所帮助
答案 4 :(得分:0)
可能的方法是为每个基本网址引入一个单一的。
您可以根据需要实例化尽可能多的RKObjectManager
个对象。但是,只有第一个将被共享。查看initWithHTTPClient:
sources。
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];