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