NSURLProtocol - startLoading не вызывается после того, как canInitWithRequest возвращает YES для ресурса страницы

У меня проблема с видео ресурсом в моем UIWebView не загружается. Это проблема только на реальном устройстве - все отлично работает на симуляторе.

Примечание. Я уже проверил это, и проблема связана с загрузкой одного и того же контента несколько раз. NSURLProtocol не запрашивается для загрузки после ответа YES на canInitWithRequest

Фактическая страница загружается нормально - по моему NSURLProtocol, это возвращает YES от canInitWithRequest (несколько раз), а затем startLoading вызывается примерно после 4-го или 5-го раза. Затем он загружает мой CSS-файл аналогичным образом. Затем я вижу, что запрос на мой видеообъект возвращается YES от canInitWithRequest, но ничего не происходит с этим. startLoading никогда не вызывается по запросу моего видео ресурса. Вот упрощенный журнал с моего устройства при загрузке страницы:

canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
START LOADING: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://cssResource
START LOADING: https://cssResource
canInitWithRequest: https://MyVideoResource

Когда я загружаю ту же самую страницу из симулятора, работающего с той же версией iOS, на том же типе устройства, журналы показывают, что ресурс действительно начинает загружаться здесь по какой-то причине:

canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://WebpageURL
START LOADING: https://WebpageURL
canInitWithRequest: https://WebpageURL
canInitWithRequest: https://cssResource
START LOADING: https://cssResource
canInitWithRequest: https://MyVideoResource
canInitWithRequest: https://MyVideoResource
START LOADING: https://MyVideoResource  -- WHY NOT ON DEVICE?

На странице остается видео, которое никогда не воспроизводится - просто белая рамка там, где она должна быть, и кнопка "Воспроизвести видео" над ней. Страница выглядит так, как будто она постоянно что-то загружает (индикатор активности в строке состояния вращается), но ничего не происходит, и сетевая активность в навигаторе отладки XCode не определена.

ТЛ; др
Кто-нибудь знает, почему загрузка этого ресурса никогда не предпринималась на моем iPhone? Очевидно, симулятор знает, что его нужно загрузить.


РЕДАКТИРОВАТЬ: Вот слегка отредактированный соответствующий код из моего NSURLProtocol

@implementation CHHTTPURLProtocol
{
    NSURLConnection *connection;
    NSHTTPURLResponse *httpResponse;
    NSData *responseData;
}

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    if (/* key exists on request */)
        return NO;
    else if (/* not http or https */)
        return NO;

    NSLog(@"canInitWithRequest: %@", request.URL.absoluteString);

    return YES;
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
    return request;
}

- (void)startLoading
{
    NSMutableURLRequest *request = [self.request mutableCopy];
    NSLog(@"START LOADING: %@", request.URL.absoluteString);
    if (authenticate) authenticate(request);
    /* add key to request */
    connection = [NSURLConnection connectionWithRequest:request delegate:self];
}

- (void)stopLoading
{
    [connection cancel];
    connection = nil;
}

/* Other methods like connection:didReceiveData: and connectionDidFinishLoding: */

+ (void)authenticateWithBlock:(AuthenticationBlock)block
{
    authenticate = block;
}

static AuthenticationBlock authenticate;

2 ответа

Я думаю, что видеоплеер, используемый в UIWebView не загружает свой контент с помощью сервисов Foundation (NSURLSession/NSURLRequestи т. д.) через какую трубу NSURProtocol, Вероятно, видеоплеер делает запросы, используя нижний уровень CFNetwork апи.

Реализация, вероятно, отличается от симулятора к устройству.

Я понял, что ваш протокол опрошен canInitWithRequest вызов, но это не обязательно означает, что игрок собирается загрузить ресурс с помощью NSURLSession/NSURLRequest,

Попытка загрузить видео через пользовательский протокол в MPMoviePlayerViewController имеет сходное поведение с тем, что вы видите: Как воспроизвести фильм с URL-адресом, используя пользовательский NSURLProtocol?

У меня нет однозначного ответа, но у меня есть пара предложений, которые могут решить эту проблему: рассматривали ли вы кеширование? Если UIWebView считает, что у него уже есть копия видео, он не будет вызывать.

когда iOS 8 получает HTTP-ответ с заголовком Keep-Alive, она сохраняет это соединение для повторного использования позже (как и должно быть), но сохраняет его больше, чем параметр timeout заголовка Keep-Alive. Видео - это последнее, что нужно загрузить, и если Mac работает быстрее, чем реальное устройство, это может быть именно так. Глядя на ваш код, если NSURLRequest равен nil после canInitWithRequest, но до startLoading, вы все равно увидите что-то в NSLog.

  1. Симулятор может использовать OSX AVFoundation для воспроизведения видео. Это означает, что фреймворки разные и на iOS поддерживается меньше кодеков.
  2. Устройство ios чувствительно к регистру, когда дело доходит до имен файлов, а симулятор - нет.
  3. Предполагая, что специфичные для iOS особенности отличаются между симулятором и реальным устройством, если это второе видео в UIWebView, оно определенно не должно воспроизводиться на iOS, но может воспроизводиться на симуляторе.
Другие вопросы по тегам