在Safari中打开WebView链接

时间:2010-12-25 15:08:32

标签: cocoa

我正在使用Cocoa开发一个应用程序,我想知道是否有方法/如何在我的webview中点击任何链接以在Safari(或默认浏览器)中启动。提前谢谢!

5 个答案:

答案 0 :(得分:22)

我自己就遇到了这个问题,并以这种方式解决了这个问题:

我的主控制器对象被设置为WebView的policyDelegate。

然后实现这个方法:

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

我需要在那里检查主机,否则当我加载WebView的初始内容(我的项目中只是一个静态html页面)时,它就是在Safari中启动的。现在,只需将实际主机(外部链接)的链接发送到Safari,这就是我想要的行为。我想我还可以在加载初始页面之前没有设置policyDelegate。

答案 1 :(得分:8)

我遇到了同样的问题,我发现的解决方案并不太直观。

如前所述,您必须使用WebPolicyDelegate中定义的<WebKit/WebPolicyDelegate.h>协议。这是一个非正式的协议,所以你不能写@interface MyDelegate : NSObject <WebPolicyDelegate>

#import <WebKit/WebPolicyDelegate.h>(或整个WebKit.h)并按如下方式实现webView:decidePolicyForNavigationAction:request:frame:decisionListener:方法:

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

然后将您的类设置为WebView的PolicyDelegate。

逻辑规定您应使用actionInformation词典中的其他键,即WebActionNavigationTypeKey,其值为可包含WebNavigationTypeLinkClicked的枚举。不幸的是,我看到的值看起来是随机的,远远超出了正确的范围(6个十进制数字整数,而枚举从0变为5)。

但是,还有其他要检查的内容,WebActionElementKey,它返回发起导航操作的HTML实体。从代码加载帧中的数据时,其值为nil,而当用户单击链接时,其值为(已解析的)<a>实体。检查非nil值是否有效。

答案 2 :(得分:7)

感谢您的提示! 我只需要将外部链接路由到Safari。要获取名称锚(带#)以显示在webView中,我执行了以下操作:

 - (void)webView:(WebView *)webView 
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
        request:(NSURLRequest *)request 
          frame:(WebFrame *)frame 
decisionListener:(id <WebPolicyDecisionListener>)listener
{
    NSDictionary *info = actionInformation;
    NSURL *url = [info objectForKey:WebActionOriginalURLKey];
    NSString *path = [url absoluteString];
    NSRange range;

    range = [path rangeOfString:@"file://"];

    if (range.location != 0) {
        // open in Safari ö
        [listener ignore];
        [[NSWorkspace sharedWorkspace] openURL:[request URL]];
    }
    else {
        // open in webView because link starts with file://...
        [listener use];
    }
}

答案 3 :(得分:0)

使用描述的方法here

答案 4 :(得分:0)

夫特

下面的Swift示例:

import Foundation
import Cocoa
import WebKit


class WebViewManager: WebView {

    private var _urlHome = NSURL(string: "http://www.apple.com")

    override init() {
        super.init()
    }

    override init(frame: NSRect) {
        super.init(frame: frame)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        //Sets current object as the receiver of policy delegate
        self.policyDelegate = self
        //Load homepage
        self.loadHomePage()
    }

    func loadHomePage() {
        let request = NSURLRequest(URL: self._urlHome!);
        self.mainFrame.loadRequest(request)
    }


    override func webView(webView: WebView!, decidePolicyForNewWindowAction actionInformation: [NSObject : AnyObject]!, request: NSURLRequest!, newFrameName frameName: String!, decisionListener listener: WebPolicyDecisionListener!) {
        println(__LINE__)
    }

    override func webView(webView: WebView!, decidePolicyForNavigationAction actionInformation: [NSObject : AnyObject]!, request: NSURLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
        println(request.URL.host)
        if request.URL.host == self._urlHome?.host {
            listener.use()
        }else {
            NSWorkspace.sharedWorkspace().openURL(request.URL)
        }
    }

}

-

不要忘记在Inspector上设置自定义类,选择WebViewManager,否则它将无效。

Custom Class

如果您希望在外部浏览器上打开点击次数,请使用此

override func webView(webView: WebView!, decidePolicyForNavigationAction actionInformation: [NSObject : AnyObject]!, request: NSURLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
    //Check action action type, if click, open an external view
    let info:NSDictionary = actionInformation as NSDictionary
    let mode:Int = info.valueForKey(WebActionNavigationTypeKey) as Int
    if mode == 0 {
        NSWorkspace.sharedWorkspace().openURL(request.URL)
        self.mainFrame.reload()
    }else{
        listener.use()
    }
}