如何在Cocoa中打开safari / chrome浏览器的外部链接

时间:2013-05-23 01:21:27

标签: macos cocoa webview webkit

我是Cocoa开发的新手。

我已阅读有关使用WebPolicyDelegate的信息。但是,我似乎无法以应有的方式工作。我希望该应用程序打开外部链接,并在Chrome或Safari等网络浏览器中启动。只有在点击链接时才会出现这种情况。

目前,我的应用的默认网址也会同时打开网页浏览器以及我应用的网页浏览功能。

我已将policyDelegate设置为我的webview,并使用以下代码进行实现:

- (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];
    }
}

任何帮助将不胜感激! :)

3 个答案:

答案 0 :(得分:15)

我可以通过将我的webView设置为PolicyDelegate来解决我的问题。

[webView setPolicyDelegate:self];

并实施以下代码:pandoraboy

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request
{
    // HACK: This is all a hack to get around a bug/misfeature in Tiger's WebKit
    // (should be fixed in Leopard). On Javascript window.open, Tiger sends a null
    // request here, then sends a loadRequest: to the new WebView, which will
    // include a decidePolicyForNavigation (which is where we'll open our
    // external window). In Leopard, we should be getting the request here from
    // the start, and we should just be able to create a new window.

    WebView *newWebView = [[WebView alloc] init];
    [newWebView setUIDelegate:self];
    [newWebView setPolicyDelegate:self];

    return newWebView;
}

- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
     if( [sender isEqual:webView] ) {
        [listener use];
     }
     else {
        [[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]];
        [listener ignore];
        [sender release];
     }
}

- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id<WebPolicyDecisionListener>)listener {
    [[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]];
    [listener ignore];
}

我希望这也可以帮助别人。 :)

答案 1 :(得分:5)

您可以检查您的网址方案,以检查是否应该在默认浏览器中打开它。

// open local urls in our app, and external in default browser
NSString *scheme = [[request URL] scheme];
if ([scheme isEqualToString:@"file"])
{
    [listener use];
}
else
{
    [listener ignore];
    [[NSWorkspace sharedWorkspace] openURL:[request URL]];
}

此代码适用于我。它是可扩展的:您可以检查自定义方案以执行一些自定义操作。

答案 2 :(得分:0)

根据上面的答案,我精心制作了以下解决方案。我在cordova-osx应用程序中使用window.open()时遇到了问题(它没有做任何事情)。这是我的修复,如果有人遇到同样的问题(改变CDVWebViewDelegate.m就像这样):

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
    return sender; //[self externalWebView:sender];
}

#pragma mark WebPolicyDelegate

- (void) webView:(WebView*) sender decidePolicyForNavigationAction:(NSDictionary*) actionInformation request:(NSURLRequest*) request frame:(WebFrame*) frame decisionListener:(id <WebPolicyDecisionListener>) listener {
    NSString* url = [[request URL] description];
    NSLog(@"navigating to %@", url);
    //[listener use];
    NSString *scheme = [[request URL] scheme];
    if ([scheme isEqualToString:@"file"])
    {
        [listener use];
    }
    else
    {
        [listener ignore];
        [[NSWorkspace sharedWorkspace] openURL:[request URL]];
    }
}

在JS中调用window.open()时,会在委托中调用createWebViewWithRequest,并返回当前的WebView(sender)。然后,这又调用当前委托的decisionPolicyForNavigationAction。使用url方案,我们决定是否应该由外部浏览器(sharedWorkspace)的WebView处理请求。