Vincent Gable’s Blog

April 22, 2009

Getting the Current URL from a WebView

Filed under: Cocoa,iPhone,MacOSX,Objective-C,Programming,Sample Code | , , ,
― Vincent Gable on April 22, 2009

UPDATED 2009-04-30: WARNING: this method will not always give the correct result. +[NSURL URLWithString:] requires it’s argument to have unicode characters %-escaped UTF8. But stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding will convert # to %23, so http://example.com/index.html#s1 would become http://example.com/index.html%23s1. Unfortunately, the two URLs are not equivalent. The un-%-escaped one refers to section #s1 in the file index.html, and the other tries to fetch the file index.html#s1 (“index dot html#s1”). I have not yet implemented a workaround, although I suspect one is possible, by building the NSURL out of bits of the JavaScript location object, rather then trying to convert the whole string.


UIWebView/WebView does not provide a way to find the URL of the webpage it is showing. But there’s a simple (and neat) way to get it using embedded JavaScript.

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script

Is a deceptively powerful method that can execute dynamically constructed JavaScript, and lets you embed JavaScript snippets in Cocoa programs. We can use it to embed one line of JavaScript to ask a UIWebView for the URL it’s showing.

@interface UIWebView (CurrentURLInfo)
- (NSURL*) locationURL;
@end
@implementation UIWebView (CurrentURLInfo) - (NSURL*) locationURL; { NSString *rawLocationString = [self stringByEvaluatingJavaScriptFromString:@"location.href;"]; if(!rawLocationString) return nil; //URLWithString: needs percent escapes added or it will fail with, eg. a file:// URL with spaces or any URL with unicode. locationString = [locationString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; return [NSURL URLWithString:locationString] } @end

With the CurrentURLInfo category, you can do aWebView.locationURL to get the URL of the page a WebView is showing.


One last note, the

if(!rawLocationString)
	return nil;

special-case was only necessary, because [NSURL URLWithString:nil] throws an exception (rdar://6810626). But Apple has decided that this is correct behavior.

Powered by WordPress