Подтвердить что ты не робот

Несколько RKObjectManager за раз (RestKit)

Я тестирую RestKit и нуждаюсь в доступе к различным BaseUrls, а также иногда получаю доступ к веб-сервису с одним и тем же базовым узлом из разных мест "сразу", и, наконец, мне также нужно получить доступ к тому же baseUrl с разными параметрами ressourcePath в одном контроллере.

В моем делете приложения я установил singleton RKObjectManager, как это.

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

Одиночный подход очень прост в работе, но я не могу понять, как отделить различные вызовы веб-сервисов.

В MyViewController, который реализует RKObjectLoaderDelegate, у меня будут два метода:

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

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

Это не создает проблем, когда MyViewController использует один одноколейный RKObjectManager для доступа к одному серверу ressourcePath с одним baseUrl.

Если я запускаю разные запросы таким образом:

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

и т.д., в том же MyController, моя проблема в том, что FLICKRPath и FOURSQUAREPath, конечно, имеют разные baseUrl, но у RKObjectManager только один?

Если я получу эту работу и могу иметь разных RKObjectManager, возникает другая проблема. Методы делегата didLoadObjects и didFailWithError получат результаты от RKObjectManagers, и я не вижу другого способа рассказать их обособленно, чем от их baseUrls. Потенциально сравнивая каждое возвращаемое значение с baseUrl и, что еще хуже, ressourcePath, в методе делегата вообще не обращается ко мне.

Если у меня есть разные RKObjectManagers, я думаю, я мог бы передавать им разные делегаты и создавать классы, предназначенные для обработки возвращаемых значений из разных baseUrls и ressourcePaths. Это означало бы, что мне пришлось создать еще одну абстракцию поверх MyController и RestKit, которая также кажется беспорядочной.

У меня есть сильное чувство, что я делаю это неправильно, источник RestKit очень впечатляет, что указывает на то, что я борюсь с каркасом. Я был бы очень признателен за понимание лучшей практики на эту тему. Я прошел через все ресурсы и примеры, которые мог найти, но не видел вышеупомянутого варианта использования. Это всегда один RKObjectManager, один baseUrl и один ressourcePath.

Спасибо заранее.

4b9b3361

Ответ 1

Поскольку ответа еще нет: использование нескольких менеджеров объектов довольно просто с помощью RestKit.

Из Wiki (Использование нескольких базовых URL-адресов (и нескольких менеджеров объектов):

Первым созданным менеджером объектов будет общий синглтон 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;
    // .......
}

Ответ 2

Изменение 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];

(добавление примечания в случае, если другие новые пользователи столкнулись с теми же проблемами, что и я).

Ответ 3

И, кстати, поскольку свойство userData также доступно в RKRequest, вы можете использовать тот же подход для загрузки/идентификации запросов.

Например, некоторый почтовый запрос:

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

Ответ 4

Как об использовании objectLoader. Вы найдете отображаемый тип объекта/класс objectLoader.objectMapping.objectClass и добавьте свои условия на его основе вместо URL

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

Надеюсь, что это поможет

Ответ 5

Возможный подход - ввести один синглтон для каждого базового url.

Вы можете создать столько объектов RKObjectManager, сколько захотите. Тем не менее, только первый станет общим. Просмотрите источники initWithHTTPClient: .

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

Мы не можем использовать метод по умолчанию sharedManager для целевого диспетчера объектов, но мы можем легко реализовать собственный синглтон. Вот пример для диспетчера объектов Google Maps:

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