0

I'm loading a train schedule URL into a UIWebView. Refreshing is slow due to the page being bloated beyond belief with site-wide CSS, JS, image, and other resources that have their response headers set to

Cache-Control:no-cache, no-store, must-revalidate
Pragma:no-cache

but have

Last-Modified:Wed, 30 Apr 2014 02:48:09 GMT

Even with

NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                     diskCapacity:30 * 1024 * 1024
                                                         diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];

those resources aren't being cached.


Question: I would like to know how to cache these resources in spite of their response headers, except for the train schedule HTML (which should not be cached). Optionally, I would like to NSlog the resources being loaded. I'm using a standard UIWebView and UIWebViewDelegate methods.

Chan
  • 269
  • 1
  • 13

1 Answers1

-1

It doesn't matter what you do to the cache itself, because it is never reaching the NSURLCache class in the first place. The default URL protocol caching policy for HTTP/HTTPS is preventing it from being cached.

To cache such requests with UIWebView, first implement and register a custom NSURLProtocol object as follows:

  • In your startLoading method, create a mutable copy of the original URL request, and add a custom header to that mutable request. It doesn't matter what name you give the header or what string value you give it, so long as the name you pick isn't likely to appear in any real headers in any request you receive. (In other words, name it something like "x-mycustomprotocoltag-watermelon", only more descriptive than that.)

    After you add the custom header, create an NSURLConnection object, specifying the protocol object as the connection's delegate, and make the URL request again.

  • In your protocol class, implement the connection:willCacheResponse: delegate method, and in that method, create an NSCachedURLResponse object yourself and return it.

  • In your canInitWithRequest: method, check for the custom header, and if you see it, return NO so that you don't end up processing the request infinitely. Similarly, if it isn't an HTTP or HTTPS request, return NO. Otherwise, return YES.

dgatwood
  • 10,129
  • 1
  • 28
  • 49