I am developing an application in Cocoa, and I would like to know if there is a way/how to make any link clicked in my webview to launch in Safari (or the default browser). Thanks in advance!
I just ran into this problem myself, and solved it this way:
My main controller object was set as the policyDelegate for the WebView.
Then implement this method:
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request frame:(WebFrame *)frame
decisionListener:(id < WebPolicyDecisionListener >)listener
{
NSString *host = [[request URL] host];
if (host) {
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
} else {
[listener use];
}
}
I needed to have the check for the host there, because otherwise when I load the initial content of the WebView (just a static html page in my project), it was being launched in Safari. Now, just links with actual hosts (external links) get sent to Safari, which is the behavior I wanted. I think I could also have not set the policyDelegate until after the initial page was loaded.
I came across the same problem and the solution I have found is not too intuitive.
As a previous answer indicated, you have to use the WebPolicyDelegate protocol, defined in <WebKit/WebPolicyDelegate.h>. It is an informal protocol, so you cannot write @interface MyDelegate : NSObject <WebPolicyDelegate>.
#import <WebKit/WebPolicyDelegate.h> (or the whole WebKit.h) and implement the webView:decidePolicyForNavigationAction:request:frame:decisionListener: method as follows:
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id <WebPolicyDecisionListener>)listener
{
if ([actionInformation objectForKey:WebActionElementKey]) {
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
else {
[listener use];
}
}
Then set your class as PolicyDelegate for the WebView.
Logic dictates you should use a different key from the actionInformation dictionary, namely WebActionNavigationTypeKey, whose value should be an enum that can include WebNavigationTypeLinkClicked. Unfortunately, the values I have seen look random and far beyond the correct range (6 decimal digits integers while the enum goes from 0 to 5).
But, there is something else to check, the WebActionElementKey, that returns the HTML entity that originates the navigation action. When loading data in the frame from code, its value is nil whereas when user clicks a link, its value is the (parsed) <a> entity. Checking it for non-nil value does the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With