I\'m trying to write an application which uses a lot of java script inside a UIWebView. And some of this java script is loaded dynamically (with jquery) when it is needed.
After some more more work I found the solution to my problem. And answer here with what I found.
The solution is to to create a custom NSURLProtocol implementation and register this in the application as handler for the http protocol. The code looks like this (I've omitted some error handling in the code):
#import "MyHttpURLProtocol.h"
@implementation MyHttpURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
return [[[request URL] scheme] isEqualToString:@"http"]; // we handle http requests
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
- (void) startLoading {
id<NSURLProtocolClient> client = [self client];
NSURLRequest* request = [self request];
NSString *pathString = [[request URL] absoluteString];
NSString* fileToLoad = nil;
if ([pathString isEqualToString:@"http://example.com/index.html"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
}
else if ([pathString hasPrefix:@"http://example.com/code.js"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"code" ofType:@"js"];
}
else if ([pathString isEqualToString:@"http://example.com/jquery-1.6.2.min.js"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"jquery-1.6.2.min" ofType:@"js"];
}
NSData* data = [NSData dataWithContentsOfFile:fileToLoad];
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[request URL] statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:[NSDictionary dictionary]];
[client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[client URLProtocol:self didLoadData:data];
[client URLProtocolDidFinishLoading:self];
}
- (void) stopLoading {}
@end
This code allows now to load the index.html file be accessing the following code:
[_webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]]];
And don't forget to register the custom protocol in your app delegate:
[NSURLProtocol registerClass:[TOHttpURLProtocol class]];
[NSURLProtocol registerClass:[MyHttpURLProtocol class]];
It's amazing how simple the solution can be after your found it. Here is the link to the updated example project: http://dl.dropbox.com/u/5426092/LocalCacheJsInjectTest-working.zip
And for completeness sake here is the link to the blog post which helped me in finding the solution: http://www.infinite-loop.dk/blog/2011/09/using-nsurlprotocol-for-injecting-test-data/