views:

1168

answers:

2

I am trying to build a custom control based on a UIWebView and compile it into a library for reuse. Everything was working just fine when I had the code all together in a single test app but I'm having some trouble setting up a the delegate for the view for a library. Of note, the sample app used interface builder and thus the delegate was set via IB.

NewsView.h:

@interface NewsView : UIWebView {
   NSObject<UIWebViewDelegate> *delegate;
}
@property (nonatomic, assign) IBOutlet NSObject<UIWebViewDelegate> *delegate;

In the implementation all of my initialization methods call a common method viewInit

NewsView.m

@implementation NewsView

@synthesize delegate;

- (void)viewInit {

    self.delegate = [[NewsViewDelegate alloc] init];
}

If the user clicks on one of the headlines in the view I need the delegate to intercept clicks and launch Safari.

NewsViewDelegate.h

@interface NewsViewDelegate : NSObject <UIWebViewDelegate> {
}

NewsViewDelegate.m

// Intercept URL events
- (BOOL)webView:(UIWebView *)myWebView shouldStartLoadWithRequest:
    (NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

    NSLog(@"URL Changed");
    // Check to see if this is a click event
    if (navigationType == UIWebViewNavigationTypeLinkClicked) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[[request URL]            absoluteString]]];
            return NO;
    }

    return YES;
}

Unfortunately shouldStartLoadWithRequest never gets called and so clicks are not being launched externally.

I'm sure I'm just missing something, any help would be greatly appreciated.

Thanks!

A: 

You are shadowing the existing delegate property of the webview. Try to simply not include the delegate property in your subclass. It should be inherited.

St3fan
Thanks St3fan, I did try that earlier and then just again but it didn't seem to do the trick. From the code above I just commented out all the delegate definition / synthesize in the .h in the viewInit method but it didn't change the behavior. I'm sure that was a problem but something else is wrong as well. Thanks again, I really appreciate your taking the time to review and advise.
A: 

It's typically a bad idea to subclass UIWebView, and the docs specifically advise against it. I don't know for sure, but my guess is that UIWebView is a class cluster.

To get the effect you want, you might try making your NewsView a plain UIView, then add the UIWebView as a subview. From there you can set the UIWebView delegate to the NewsViewDelegate without worrying about the subclass.

The best method might be to create a NewsViewController class that loads your NewsView and implements the UIWebViewDelegate methods itself and set the NewsView webView delegate to your NewsViewController.

Tyson Tune
Thank you Tyson, I will give that change a try and report back. I appreciate your help. Is there a link that you could share regarding the advice not to subclass? I read the overview at http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html and didn't see it (or just have doc fatigue and missed it).Thanks again!
Those are the OS X WebView reference, you should look at the iPhone UIWebView reference. http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/Reference/Reference.htmlLuckily the iPhone docs always show up first in my searches. Otherwise I'm sure I'd probably do the same thing all the time. :-)
kubi
Like kubi said, it's in the iPhone docs here: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/Reference/Reference.html under Subclassing notes in the overview. Matt Gallagher has a good post about subclassing class clusters here: http://cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html
Tyson Tune
I was finally able to work on this again and creating a UIView and containing a UIWebView did work well, thank you for the advice Tyson. I did also want to mention I was able to get that subclassed UIWebView to work by having it also be the UIWebViewDelegate:@interface NewsView : UIWebView <UIWebViewDelegate> Though I'm not sure when/if that would fall apart somewhere else. The UIView works very well and also lets me keep the delgates in separate file which I prefer.