NSURLProtocol - 在canInitWithRequest之后未调用的startLoading为页面资源

时间:2015-10-12 20:05:02

标签: ios objective-c uiwebview nsurlprotocol

我遇到了UIWebView中的视频资源未加载的问题。这只是实际设备上的一个问题 - 一切都在模拟器上完美运行。

注意:我已经检查了这个问题,其中的问题与多次加载相同的内容有关。 NSURLProtocol isn't asked to load after YES response to canInitWithRequest

实际页面在我的自定义NSURLProtocol中正常加载,它从YES返回canInitWithRequest(多次),然后在大约第4或第5次后调用startLoading时间。然后它以类似的方式加载我的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的Debug导航器中的网络活动是扁平化的。

TL;博士
有谁知道为什么从未在我的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 个答案:

答案 0 :(得分:0)

我没有明确答案,但我确实有一些建议可以解决这个问题: 你考虑过缓存吗? If the UIWebView thinks it already has a copy of the video, it won't call

<击> when iOS 8 receive an HTTP response with a Keep-Alive header, it keeps this connection to re-use later (as it should), but it keeps it for more than the timeout parameter of the Keep-Alive header。视频是最后加载的东西,如果Mac比真实设备更快,它可能就是它。查看你的代码,如果在canInitWithRequest之后但在startLoading之前NSURLRequest为零,你仍会在NSLog中看到一些东西。

  1. 模拟器可能正在使用OSX AVFoundation播放视频。这意味着iOS上支持frameworks are differentfewer codecs
  2. <击> The ios device is case sensitive when it comes to file names whilst the simulator is not.
  3. 假设iOS-Specific Considerations在模拟器和真实设备之间有所不同,如果这是UIWebView中的第二个视频,它绝对不能在iOS上播放但可能在模拟器上播放。

答案 1 :(得分:0)

我最好的猜测是UIWebView中使用的视频播放器没有使用基础服务(NSURLSession/NSURLRequest等)来加载它的内容,这些服务通过NSURProtocol。可能视频播放器正在使用较低级CFNetwork api发出请求。

实施可能因模拟器而异。

我知道您的协议是使用canInitWithRequest调用进行轮询的,但这并不一定意味着播放器将使用NSURLSession/NSURLRequest实际加载资源。

尝试通过自定义协议将视频加载到MPMoviePlayerViewController中的行为与您所看到的行为类似:How to play movie with a URL using a custom NSURLProtocol?