Overriding NSURLCache's cachedResponseForRequest to cache UIWebView assets with Three20
Asked Answered
T

0

1

I need to cache a web-sourced image (i.e. not bundle sourced) that is going into a webview. Normally I'd just request the image and convert it into base-64 and stick it in the HTML, but if I have 100 images in line I can't quite do that.

So I searched around a bit and found a way to grab the image request by subclassing NSURLCache and overriding cachedResponseForRequest. My code is below.

I'm able to do the request just fine, I can get the data back and print it out, I made a UIImage from the data and got its size to know that it's definitely there, etc. But when I return the cachedResponseForRequest itself, and look at the UIWebView, it just shows a missing image. I've been agonizing over this for a day and can't figure it out. I've looked at example after example and no cigar.

Can anyone help me solve this? It's driving me nuts..

Here is the content of the .m file of my NSURLCache subclass. GimageData is an instance variable for storing the current image data received.

Just so you know, the reason why I do a search/replace for http___ to http:// is that http:// links apparently don't get picked up by this method, so I made the link look like it's something that's in the bundle then I revert the URL for retrieval.

- (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request
{
    NSURL *url = [request URL];

 NSLog(@"Url requested is: %@", [url absoluteString] );


 NSRange textRange;

 textRange = [[[url absoluteString] lowercaseString] rangeOfString:[@"http___" lowercaseString]];
 NSCachedURLResponse *cachedResponse = nil;

 if(textRange.location != NSNotFound) {

  //Does contain the substring
  NSLog(@"Found an http___ request");
  NSString *newURL = [[url absoluteString] substringFromIndex:textRange.location];
  newURL = [newURL stringByReplacingOccurrencesOfString:@"http___" withString:@"http://"];
  NSLog(@"New url: %@", newURL);

  TTURLDataResponse *response = [[TTURLDataResponse alloc] init];
  TTURLRequest *imageRequest = [[TTURLRequest alloc] initWithURL:newURL
                 delegate:self];
  imageRequest.response = response;
  [response release];
  [imageRequest sendSynchronously];


  if ( GimageData ) {
   NSLog(@"Response: %d as %@", [GimageData bytes], [GimageData class]);
   NSLog(@"Storing under: %@ ", request.URL );

   NSURLResponse* Nresponse = [[NSURLResponse alloc] initWithURL:request.URL 
                 MIMEType:nil 
             expectedContentLength:[GimageData length] 
               textEncodingName:nil];

   cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:Nresponse
                   data:GimageData];

   [imageRequest release];
   [Nresponse release];
   NSLog(@"Cached the response.");
  }

 }

 if (cachedResponse == nil) {
  NSLog(@"Response is nil so getting super's cache");
  cachedResponse = [super cachedResponseForRequest:request];
 }

    return cachedResponse;
}


- (void)requestDidFinishLoad:(TTURLRequest*)request {
 NSLog(@"Request did finish loading.");

 TTURLDataResponse *response = request.response;
// NSURL *url = [NSURL URLWithString:request.urlPath];

 GimageData = response.data;


 if ( GimageData ) {
  NSLog(@"And we got the data.");
 }
 else {
  NSLog(@"But there was no data in the response.");
 }

}
Tripping answered 9/7, 2010 at 18:51 Comment(1)
It is in fact possible to convert the images into base64 and insert them into the HTML if you make sure to send the request synchronously. Otherwise, the images load after the HTML loads and you have to load the HTML twice. It may in fact be the more elegant solution than having to intercept the NSURLCache request.Tripping

© 2022 - 2024 — McMap. All rights reserved.