15

I am working on a image-text mixture page on iOS. I know it is possible for me to use UIWebView to achieve the goal. But the problem is, user may need to read the page offline. For the text part, I can save the html to the disk and load it in the offline mode. But how about images? Is it possible to cache the images to the disk and the UIWebView can still be able to display them?

Thank you!

mr.pppoe
  • 3,945
  • 1
  • 19
  • 23

1 Answers1

15

The ASIHTTPRequest project has a class called ASIWebPageRequest which is designed to do exactly what you want. If you're okay with adding an additional dependency to your project then I think it's a good solution for you: ASIWebPageRequest.

On the page I liked above there are some good examples of how to use it but I'll include one of them here for completeness:

- (IBAction)loadURL:(NSURL *)url
{
   // Assume request is a property of our controller
   // First, we'll cancel any in-progress page load
   [[self request] setDelegate:nil];
   [[self request] cancel];

   [self setRequest:[ASIWebPageRequest requestWithURL:url]];
   [[self request] setDelegate:self];
   [[self request] setDidFailSelector:@selector(webPageFetchFailed:)];
   [[self request] setDidFinishSelector:@selector(webPageFetchSucceeded:)];

   // Tell the request to embed external resources directly in the page
   [[self request] setUrlReplacementMode:ASIReplaceExternalResourcesWithData];

   // It is strongly recommended you use a download cache with ASIWebPageRequest
   // When using a cache, external resources are automatically stored in the cache
   // and can be pulled from the cache on subsequent page loads
   [[self request] setDownloadCache:[ASIDownloadCache sharedCache]];

   // Ask the download cache for a place to store the cached data
   // This is the most efficient way for an ASIWebPageRequest to store a web page
   [[self request] setDownloadDestinationPath:
      [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:[self request]]];

   [[self request] startAsynchronous];
}

- (void)webPageFetchFailed:(ASIHTTPRequest *)theRequest
{
   // Obviously you should handle the error properly...
   NSLog(@"%@",[theRequest error]);
}

- (void)webPageFetchSucceeded:(ASIHTTPRequest *)theRequest
{
   NSString *response = [NSString stringWithContentsOfFile:
      [theRequest downloadDestinationPath] encoding:[theRequest responseEncoding] error:nil];
   // Note we're setting the baseURL to the url of the page we downloaded. This is important!
   [webView loadHTMLString:response baseURL:[request url]];
}
xoebus
  • 812
  • 7
  • 18
  • Thanks much for this sample, will try it later. Could you tell me how the ASIReplaceExternalResourcesWithData can embed the data to the page? The page remains a html file in the cache, right? Does the request modify the original html? – mr.pppoe Jul 15 '11 at 03:17
  • Yep, you're right. ASI modifies the page and replaces those assets with [Data URIs](http://en.wikipedia.org/wiki/Data_URI_scheme). Alternatively, you can use a different URL replacement mode called `ASIReplaceExternalResourcesWithLocalURLs` which will download the resources as files but still modify the HTML to point at these local files. – xoebus Jul 15 '11 at 11:23
  • Thanks xoebus. I also found out that to enable offline browsing, I need to add this line of code: `request.cachePolicy = ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy;` – Joseph Lin Aug 31 '11 at 23:53