我正在使用Cocoa开发一个应用程序,我想知道是否有方法/如何在我的webview中点击任何链接以在Safari(或默认浏览器)中启动。提前谢谢!
答案 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,否则它将无效。
如果您希望在外部浏览器上打开点击次数,请使用此
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()
}
}