iPhone SDK Tip: Firing custom events when a link is clicked in a UIWebView

Well I have been asked this a few times and I can see how it would be a very helpful addition to the UIWebView‘s feature set. What I am talking about is adding the ability to intercept the event generated when a user selects a link in a webpage being displayed with a UIWebView, this will then allow you to perform any action that you want.

When would you use this I hear you say? Well one person asked me if I knew how to append the users current location onto all HTTP requests? and another just wanted to know how to perform custom actions from an embedded UIWebView.

Once again I will be extending the “Build your very own Web Browser!”, if you haven’t already completed it then I suggest that you head over there now and spend 5 minutes reading it and then downloading the project files at the end.

Start by opening up the WebBrowserTutorialAppDelegate.h file and editing the @interface line to read:

@interface WebBrowserTutorialAppDelegate : NSObject <UIWebViewDelegate> {

What we have done is to make the main AppDelegate a delegate for the UIWebView as well.

Now we need to set our webView to have the main AppDelegate as its delegate, you can do this by opening up WebBrowserTutorialAppDelegate.m and putting the following line just inside the applicationDidFinishLaunching function:

webView.delegate = self;

That is all pretty self explanatory, it just sets the delegate of our webView to self, which in this case is our main application delegate.

Now we are pretty much done, we just need to add the function to catch the link clicks. To do this we need to add a new function, copy the content below to the WebBrowserTutorialAppDelegate.m file:


- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
	NSURL *url = request.URL;
	NSString *urlString = url.absoluteString;
	NSLog(urlString);
	return YES;	
}

This function will catch all requests and allow you to either manipulate them and pass them on or to perform your own custom action and stop the event from bubbling.

The first line gets the URL of the request, this is the contents inside the href attribute in the anchor tag.
The next line converts the URL to a string so we can log it out. You can access many parts of the NSURL, here are some of them and brief description of what they do.

* absoluteString – An absolute string for the URL. Creating by resolving the receiver’s string against its base.
* absoluteURL – An absolute URL that refers to the same resource as the receiver. If the receiver is already absolute, returns self.
* baseURL – The base URL of the receiver. If the receiver is an absolute URL, returns nil.
* host – The host of the URL.
* parameterString – The parameter string of the URL.
* password – The password of the URL (i.e. http://user:pass@www.test.com would return pass)
* path – Returns the path of a URL.
* port – The port number of the URL.
* query – The query string of the URL.
* relativePath – The relative path of the URL without resolving against the base URL. If the receiver is an absolute URL, this method returns the same value as path.
* relativeString – string representation of the relative portion of the URL. If the receiver is an absolute URL this method returns the same value as absoluteString.
* scheme – The resource specifier of the URL (i.e. http, https, file, ftp, etc).
* user – The user portion of the URL.

Then the third line simply logs the URL to the console, so you will new to open up the console while you run this in the simulator to see the results.

Finally the forth line returns YES, this will allow the UIWebView to follow the link, if you would just like to catch a link and stop the UIWebView from following it then simply return NO.

I hope this will help someone to make a browser with some nice user interaction features.

Thanks,
-Dean

0
Share

18 Comments

  1. Dean,

    This is nice but it would be more complete if you explained how people could retrun NO from shouldStartLoadWithRequest then modify the request and reinject it to the UIWebView via Load request.

    without having tried it, I’d be interested to know if that code goes recursive. My gut feel is YES.

    r

  2. derek

    Note that the Request is actually (based on one quick test :-) an instance of NSMutableURLRequest, so should allow you to manipulate the URL etc once cast.

  3. Ror

    Doesn’t works.

  4. Easyldur

    Hey, thanks for your code, it’s helping a lot with a little project I have on my mind…

    My problem is that, while I’m not new to coding (I’m not an expert, tho) I’m totally new to obj-c.

    I read everything you wrote, but I can’t understand WHEN the function is actually called. Everything works as stated, but I can’t understand why.

    Is it a kind of override of some pre-existing “webView” function? The fact that it has the same name of the webView variable makes me wonder if it exists before.

    Thanks for your tutorial! They’re helping a lot!

  5. Dean

    @EasyIdur: No problems, glad to help! In response to your question, it is overriding a pre-existing function, the function we are overriding is called “shouldStartLoadWithRequest” and is part of the UIWebView Class. There are many documented classes that you can override for every class.

    Thanks,
    -Dean

  6. yah13oaaa

    Nice site, thanks for information!

  7. James Ming

    When I

    When returned a NO, the intiial, “http://dblog.com.au/”, did not launch. Makes sense since NO stops it from browsing that initial page. I want to make it stop following links after that initial page. Here is what I did to solve that problem:

    - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    NSURL *url = request.URL;
    NSString *urlString = url.absoluteString;
    NSLog(@”this is a test %@”,urlString);

    if([urlString isEqualToString: @"http://dblog.com.au/"]){
    return YES;
    }
    else{
    return NO;
    };

    }

  8. Dean, i am new to iphone/obj-c. Have been a flash programmer for long. Thanks for this post, its amazing.

    As practice, I tried to create the whole thing from scratch, and when I run it on simulator, i just see a blank screen with status bar and soon after that an error in dealloc method.

    I used interface builder, but don’t know which xib to edit (there are two). Is it always necessary to use xib? I prefer coding; not designing. I placed web view ui to WebViewController and I just cant get beyond the blank screen. I am getting petrified my the interface builder and it is horribly discouraging to use xcode along with interface builder.

    Please suggest me how to understand IB and how I finally run my app just the way your sample runs.

    Thanks.

    Best
    Sam

  9. Kieran

    I tried following what james said but it isn’t working for me. I need to get the url but after it gets the first url stop getting more and continue loading the page. So I basically want urlStirng to = the first url found then load that url.

    How can I achieve this?

  10. Gene

    Is there a way this can be made to call a second local html file? When I click the link the debugger never reaches: – (BOOL)webView

  11. James

    Gene: My guess is you didn’t set your delegate to self. I had that problem, trying to use this example in different code.

  12. Peter

    Opening the webpage (or another one) in safari works great. I am unable to open it in the webView (or a new one). With/without modifying the request. Any suggestions?

    Thanks for the tutorial

  13. aniruddha

    can anybody explain how to catch button click events which is present on html page

  14. aniruddha

    i would like to know how to get input of textfield present in HTML in backend app

  15. jgraham

    I’m trying to access links that point to the iTunes store from within a Web View but they do not work. They work fine from within Safari. I even tried putting target=”_blank” in the link to open a new window when the link is clicked but that did not work either. Here’s an example of a link:

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?i=31739259&id=31739244&s=143441&uo=4

    I need a way access the iTunes music store from within the web view but I’d rather do it in HTML is possible.

    Thanks.

  16. Sam

    Dean–
    Just wanted to thank you SO MUCH. I’ve been trying to figure out how to do this for quite some time.

    Thanks!
    -Sam

  17. Ronald

    jgraham,
    I am facing same issue, opening itunes URL from within webview does not work.
    Any solutions already? Would be much appreciated.
    Thanks, Ronald

  18. amit

    Dean, had a query regarding shouldStartLoadWithRequest. My observation is that this method does get invoked when a new URL is loaded or a link is clicked within UIWebView.

    But this method doesn’t seem to get invoked for embedded links within the HTML being loaded. Do you know a way how I can intercept all the embedded link sub-requests within shouldStartLoadWithRequest?

    Thanks.

  19. Bananarama

    can i use this somehow to download binary files and if yes how?

  20. patrick

    For James Ming et al., who want to only have this happen -after- initial page load (that is, on a click event w/in the UIWebView):
    - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    if (navigationType == UIWebViewNavigationTypeLinkClicked) {
    //do things here
    }
    }

  21. kbs11

    Hi, Dean.
    I am very new in developing iPhone Applications. I want to ask you if there is any possibility to read the sensors such as accelerometer in the browser window? I want to make use of these data for my application. Waiting for your reply.
    Thanks a lot in advance.

    kbs11

  22. vijay

    hi dean,

    this is vijay,actually i have seen your all tutorial…it was a good effort…i have try to do all tutorial..all the coding simply and cute.now..i want chart based application…real want ur helpful..and i hope to u dan..

    thanks…

  23. vimal m

    hi
    Thank you for giving that above line of code
    but i have a doubt. When i click the inner link in webview that called shouldloadrequest method only once
    get called. if again click the same link that method not get called whats the problem
    i am awaiting for your reply.

  24. Vincenzo Nafta

    Thank you man, a problem of month solved in 20 minutes

Trackbacks for this post

    Leave a Reply