Как расширить AFNetworking 2.0 для объединения запросов

У меня есть пользовательский интерфейс, в котором один и тот же URL-адрес изображения может быть запрошен несколькими UIImageViews в разное время. Очевидно, что если запрос от одного из них завершен, то возврат кэшированной версии работает, как и ожидалось. Однако, особенно в более медленных сетях, я хотел бы иметь возможность совмещать запросы URL-адреса изображения с любым текущим/ожидающим HTTP-запросом для того же URL-адреса.

На HTTP-сервере это называется объединением запросов, и я хотел бы сделать то же самое в клиенте — объединить разные запросы для одного и того же URL-адреса в один запрос, а затем выполнить обратный вызов отдельно для каждого из вызывающих абонентов). Запросы для этого URL-адреса не запускаются одновременно.

Как лучше всего это сделать?

Я думаю, что переписать UIImageView + AFNetworking может быть самым простым способом:

  • проверьте af_sharedImageRequestOperationQueue, чтобы узнать, есть ли у него операция с тем же запросом
  • если у меня уже есть операция в очереди или запущенная, добавьте себя в некоторый список обратных вызовов/блоков, которые будут вызываться при успехе/неуспехе
  • если у меня нет операции, то создайте ее как обычно
  • в setCompletionBlockWithSuccess для вызова каждого из блоков по очереди.

Есть более простые альтернативы?


person user2831945    schedule 25.06.2014    source источник


Ответы (1)


Я столкнулся с похожей проблемой и решил, что ваш способ самый простой. Еще одна сложность заключается в том, что для этих загрузок требуются специальные учетные данные, и поэтому они должны проходить через собственную очередь операций. Вот код из моей категории UIImageView, чтобы проверить, находится ли определенный URL-адрес в процессе:

NSUInteger foundOperation = [[ConnectionManager sharedConnectionManager].operationQueue.operations indexOfObjectPassingTest:^BOOL(AFHTTPRequestOperation *obj, NSUInteger idx, BOOL *stop) {
    BOOL URLAlreadyInFlight = [obj.request.URL.absoluteString isEqualToString:URL.absoluteString];
    if (URLAlreadyInFlight) {
        NSBlockOperation *updateUIOperation = [NSBlockOperation blockOperationWithBlock:^{
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.image = [[ImageCache sharedImageCache] cachedImageForURL:URL];
            }];
        }];
        //Makes updating the UI dependent on the completion of the matching operation.
        [updateUIOperation addDependency:obj];
    }

    return URLAlreadyInFlight;
}];

Удалось ли вам найти лучшее решение?

РЕДАКТИРОВАТЬ: Что ж, похоже, мой метод обновления пользовательского интерфейса просто не может работать, так как блоки завершения операции запускаются асинхронно, поэтому операция завершается до запуска блоков. Однако мне удалось изменить кеш изображений, чтобы иметь возможность добавлять обратные вызовы, когда определенные URL-адреса кэшируются, что, похоже, работает правильно. Таким образом, этот метод будет правильно обнаруживать, когда определенные URL-адреса находятся в полете, и сможет предпринять действия с этим знанием.

person Jon Shier    schedule 03.08.2014