McDermott
McDermott

Reputation: 1035

iOS: Open UIWebView with local javascript files

I would like to open a website in an UIWebView, but I wan't to load the javascript files from the app's Documents folder (because of bandwidth). Is this possible?

Upvotes: 2

Views: 4629

Answers (2)

Karl
Karl

Reputation: 1233

Yes, you would need to create a custom NSURLProtocol as in this Post: https://stackoverflow.com/a/5573155/244160. Make an appropriate check in canInitWithRequest: and deliver your Javascript with the proper content-type according to the sample.

Update:

Here's a quick shot for a sample implementation:

@interface LocalJSURLProtocol : NSURLProtocol    
@end

@implementation LocalJSURLProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{

    return [request.URL.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame && [request.URL.lastPathComponent hasSuffix:@"js"]);
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
    return request;
}

- (void)startLoading
{
    NSURLRequest *request = self.request;

    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL]
                                                        MIMEType:@"text/javascript"
                                           expectedContentLength:-1
                                                textEncodingName:nil];

    NSString *localFilePath = [[NSBundle mainBundle] pathForResource:@"sample.js" ofType:nil];
    NSData *data = [NSData dataWithContentsOfFile:localFilePath];

    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [self.client URLProtocol:self didLoadData:data];
    [self.client URLProtocolDidFinishLoading:self];

}

- (void)stopLoading
{
}

@end

And you register the protocol like this [NSURLProtocol registerClass:[LocalJSURLProtocol class]]; before starting to load. This will intercept the request in your UIWebView and you have the chance to inject your own Javascript code for the request file.

Upvotes: 4

Yaniv Efraim
Yaniv Efraim

Reputation: 6713

(please see my edit below - it might be possible to work with local assets and remote html files, by using custom protocol)

It is not possible to use a local js file (or any local file) on an internet file. It is similar to the fact that you cannot open a local javascript file on a website from a regular desktop browser.

What you can do is call your website's page, save the response's html as a local html file (on your documents folder), and change the js url to be local as well. The url should be relative. For example:

documents
- myapp
-- index.html
-- scripts.js

inside index.html you can change the js src to be:

<script src="scripts.js" />
  • comments:
    1. I assume that you can access and edit the webpage.
    2. You can do a nice fallback in case the local js file was not downloaded. Similar to jQuery's cdn fallback to local file, we can do the opposite thing and do a fallback to server's file (jQuery is just for example. It can be done with any js file just by testing for namespace's existence:
    <script src="jquery-2.0.0.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js'

type='text/javascript'%3E%3C/script%3E")); }

Hope that helps!

EDIT:

After reviewing this post, you might be able to access local files from remote html file (in his example he is working with local html file, but it might work with a remote on as well)

Upvotes: -1

Related Questions