一次多个 RKObjectManager (RestKit)

发布于 2024-11-11 14:06:50 字数 1787 浏览 14 评论 0原文

我正在测试 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 将从两个 RKObjectManager 接收结果,除了它们的 baseUrl 之外,我看不到任何其他方法来区分它们。在委托方法中将每个返回值与 baseUrl 甚至更糟糕的 ressourcePath 进行比较对我来说根本没有吸引力。

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

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

先感谢您。

I am testing out RestKit and need to access different BaseUrls and also sometimes access a web service with the same baseUrl from different places "at once", lastly I also need to access the same baseUrl with different ressourcePaths in the same controller.

In my app delegate I set up the RKObjectManager singleton like this.

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

The singleton approach is really easy to work with, I however can't figure out how to separate the different web service calls.

In MyViewController, which implement the RKObjectLoaderDelegate, I will have the two methods:

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

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

This causes no problems when MyViewController uses one RKObjectManager singleton to access one ressourcePath with one baseUrl.

If I start different requests in this way:

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

and so on, within the same MyController, my problem is that FLICKRPath and FOURSQUAREPath of course has different baseUrl, but the RKObjectManager only has one?

If I get this working and can have different RKObjectManagers another problem arises.
The delegate methods didLoadObjects and didFailWithError will receive results from both RKObjectManagers and I can't see any other way to tell them apart than from their baseUrls. Potentially comparing each return value with a baseUrl and, even worse, a ressourcePath, in the delegate method does not appeal to me at all.

If I have different RKObjectManagers I guess I could pass them different delegates and build classes dedicated to deal with the return values from different baseUrls and ressourcePaths. This would mean I had to build yet another abstraction on top of MyController and RestKit, which also seems messy.

I have a strong feeling I am going about this in the wrong way, the RestKit source is very impressive which indicates that is me fighting the framework. I would really appreciate some best practice insights on the subject. I have been through all the resources and examples that I could find but have not seen the above use case. It is always one RKObjectManager, one baseUrl and one ressourcePath.

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

挽梦忆笙歌 2024-11-18 14:06:50

由于还没有公认的答案:使用 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;
    // .......
}

Since there is no accepted answer yet: using multiple object managers is quite simple using RestKit.

From the Wiki (Using Multiple Base URLs (and Multiple Object Managers):

The first object manager you create will be the shared singleton
RestKit uses by default. But by creating additional object managers,
you can pull from their BaseURLs as needed, just be sure to retain
these new managers.

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

Depending on your application, you may want to put this second object
manager in a more accessible place, like a retained property on the
AppDelegate, so that it's easy to pull from as needed.
In the event that you need to differentiate between the results from
your two (or more) object managers, simply set an identifier in the
userData for the queries.

- (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;
    // .......
}
仅此而已 2024-11-18 14:06:50

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

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

API change:

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

doesn't compile in RestKit v.0.10.3 (loadObjectsAtResourcePath:delegate: returns void). That method just wraps a few lines of code, though, so you can still get at the loader, and add userData, with the following:

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

(adding note in case other new users run into the same issues I did).

等风来 2024-11-18 14:06:50

顺便说一句,由于 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>;
}];

And by the way, since userData property is also available on RKRequest, you can use the same approach for loading/identifying requests.

For example, some post request:

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>;
}];
凡尘雨 2024-11-18 14:06:50

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

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

希望它会有所帮助

How about using objectLoader.
You'll find the mapped object type/Class objectLoader.objectMapping.objectClass and add your conditions based on it instead of the url

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

Hope it will help

千鲤 2024-11-18 14:06:50

可能的方法是为每个基本 URL 引入一个单例

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

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

Possible approach is to introduce one singletone for each base url.

You can instantiate as many RKObjectManager objects as you want. However, only the first one will become shared. Look into initWithHTTPClient: sources.

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

We can't use default sharedManager method to target specific object manager but we can easily implement our own singleton. Here's an example for Google Maps object manager:

@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

Usage:

CGObjectManager *googleMapsManager = [GMObjectManager sharedInstance];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文