7

私はWebKitを使用して本当に基本的なCocoaアプリケーションを構築し、その中にFlash/Silverlightアプリケーションを表示しています。非常に基本的なものであり、ブラウザ自体であるという意図はありません。

<a href="..." />これまでのところ、Safariの新しいインスタンスで基本的なhtmlリンク()を開くことができました。

[[NSWorkspace sharedWorkspace] openURL:[request URL]];

window.open()今、私の難しさは、JavaScriptで使用されているときにSafariの新しいインスタンスでリンクを開くことです。私は「考えます」(そしてこれによって、私はコードをハッキングしていて、実際に行ったかどうかはわかりません)WebViewを設定し、policyDelegateその実装によってこの種の作業を行いました

-webView:decidePolicyForNavigationAction:request:frame:decisionListener:

デリゲートメソッド。ただし、これにより、動作が不安定になりました。

簡単な質問ですが、window.open()が呼び出されたときにリンクがSafariの新しいインスタンスで開かれるようにするにはどうすればよいですか。

ありがとう

大きなポイントですが、私は通常.NET開発者であり、Cocoa/WebKitを使用して数日しか経っていません。

4

7 に答える 7

9

私は昨夜から進歩を遂げ、問題の一部を突き止めました。

私はすでに使用webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:しており、アンカータグで動作するようになりましたが、JavaScript が呼び出されたときにメソッドが呼び出されないようです。

ただし、window.open()呼び出されたときwebView:createWebViewWithRequest:requestに、ここで Safari で強制的にウィンドウを開こうとしましたが、要求は常に null です。そのため、URLを読み取ることはできません。

私はいくつかの検索を行いましたが、これは既知の「誤機能」のようですが、回避する方法を見つけることができませんでした.

私が理解createWebViewWithRequestしていることから、新しいwebviewを作成できるようになり、要求されたURLが新しいwebViewに送信されて読み込まれます。 これは、私がこれまでに見つけた中で最良の説明です。

そのため、多くの人がこの問題を指摘していますが、私は自分のニーズに合った解決策をまだ見つけていません。もう一度、もう少し深く掘り下げてみdecidePolicyForNewWindowActionます。

ありがとう!

于 2008-11-07T16:02:55.710 に答える
6

さて、私はダミーのwebViewを作成し、frameLoadデリゲートを処理するカスタムクラスに設定することで処理しています

- (void)webView:decidePolicyForNavigationAction:actionInformation :request:frame:decisionListener:

そこに新しいウィンドウが開きます。

コード:

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
    //this is a hack because request URL is null here due to a bug in webkit        
    return [newWindowHandler webView];
}

および NewWindowHandler :

@implementation NewWindowHandler

-(NewWindowHandler*)initWithWebView:(WebView*)newWebView {
    webView = newWebView;

    [webView setUIDelegate:self];
    [webView setPolicyDelegate:self];  
    [webView setResourceLoadDelegate:self];

    return self;
}

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

-(WebView*)webView {
    return webView;
}
于 2009-02-04T10:20:31.713 に答える
4

webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:リクエストが常に であるというバグがあるようですが、通常のリンクと JavaScriptのリンクnilの両方で機能する堅牢なソリューションがあります。target="_blank"

基本的に、私は別のエフェメラル WebView を使用して、新しいページの読み込みを処理します。Yoni Shalom に似ていますが、もう少しシンタックス シュガーがあります。

これを使用するには、まず WebView のデリゲート オブジェクトを設定します。この場合、自分自身をデリゲートとして設定します。

webView.UIDelegate = self;

次に、デリゲート メソッドを実装しwebView:createWebViewWithRequest:、ブロック ベースの API を使用して、新しいページが読み込まれたときに何かを行います。この場合、外部ブラウザーでページを開いています。

-(WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
    return [GBWebViewExternalLinkHandler riggedWebViewWithLoadHandler:^(NSURL *url) {
        [[NSWorkspace sharedWorkspace] openURL:url];
    }];
}

それだけです。これが私のクラスのコードです。ヘッダ:

//  GBWebViewExternalLinkHandler.h
//  TabApp2
//
//  Created by Luka Mirosevic on 13/03/2013.
//  Copyright (c) 2013 Goonbee. All rights reserved.
//

#import <Foundation/Foundation.h>

@class WebView;

typedef void(^NewWindowCallback)(NSURL *url);

@interface GBWebViewExternalLinkHandler : NSObject

+(WebView *)riggedWebViewWithLoadHandler:(NewWindowCallback)handler;

@end

実装:

//  GBWebViewExternalLinkHandler.m
//  TabApp2
//
//  Created by Luka Mirosevic on 13/03/2013.
//  Copyright (c) 2013 Goonbee. All rights reserved.
//

#import "GBWebViewExternalLinkHandler.h"

#import <WebKit/WebKit.h>

@interface GBWebViewExternalLinkHandler ()

@property (strong, nonatomic) WebView                           *attachedWebView;
@property (strong, nonatomic) GBWebViewExternalLinkHandler      *retainedSelf;
@property (copy, nonatomic) NewWindowCallback                   handler;

@end

@implementation GBWebViewExternalLinkHandler

-(id)init {
    if (self = [super init]) {
        //create a new webview with self as the policyDelegate, and keep a ref to it
        self.attachedWebView = [WebView new];
        self.attachedWebView.policyDelegate = self;
    }

    return self;
}

-(void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
    //execute handler
    if (self.handler) {
        self.handler(actionInformation[WebActionOriginalURLKey]);
    }

    //our job is done so safe to unretain yourself
    self.retainedSelf = nil;
}

+(WebView *)riggedWebViewWithLoadHandler:(NewWindowCallback)handler {
    //create a new handler
    GBWebViewExternalLinkHandler *newWindowHandler = [GBWebViewExternalLinkHandler new];

    //store the block
    newWindowHandler.handler = handler;

    //retain yourself so that we persist until the webView:decidePolicyForNavigationAction:request:frame:decisionListener: method has been called
    newWindowHandler.retainedSelf = newWindowHandler;

    //return the attached webview
    return newWindowHandler.attachedWebView;
}

@end

Apache 2 としてライセンスされています。

于 2013-03-13T10:17:05.687 に答える
2

すべての投稿を読むことで、私は簡単な解決策を思いつきました。すべての関数は同じクラスにあり、ブラウザでリンクを開きます。

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {

    return [self externalWebView:sender];
}




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

-(WebView*)externalWebView:(WebView*)newWebView
{
     WebView *webView = newWebView;

    [webView setUIDelegate:self];
    [webView setPolicyDelegate:self];
    [webView setResourceLoadDelegate:self];
    return webView;
}
于 2013-12-09T21:42:19.637 に答える
2

どのような異常な動作が見られるかについては言及していません。簡単に考えられるのは、デリゲート メソッドを実装するときに、デリゲートに渡されたWebPolicyDecisionListenerの ignore メソッドを呼び出して、クリックを無視していることを Web ビューに伝えるのを忘れていたことです。

それが問題ではない場合、表示しているコンテンツをどの程度制御できますか? ポリシーデリゲートは、すべてのリソース負荷をフィルタリングする簡単なメカニズムを提供し (発見したように)、すべての新しいウィンドウはwebView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:を介して開きます。すべての window.open 呼び出しは、新しいウィンドウをトリガーする他のものと同様に、それを通過する必要があります。

アプリ内に保持したい他のウィンドウが開いている場合は、もう少し作業を行う必要があります。デリゲートに渡される引数の 1 つは、イベントに関する情報を含むディクショナリです。WebActionElementKey には、リンクの元の dom コンテンツを含む、多くの詳細を含む辞書があります。そこを調べたい場合は、実際の DOM 要素を取得し、href のテキストをチェックして、それが window.open で始まっているかどうかを確認します。それは少し重い重量ですが、きめ細かい制御が必要な場合は、それが得られます.

于 2008-11-07T10:30:59.947 に答える
0

新しい WebView を返し、そのloadRequest:メソッドが呼び出されるのを待つ代わりwindow.openに、WebView の JSContext の関数を上書きすることになりました。

まず、コントローラーを WebView の WebFrameLoadDelegate に設定します。

myWebView.frameLoadDelegate = self;

次に、デリゲート メソッドでwindow.open関数を上書きし、代わりにそこで URL を処理できます。

- (void)webView:(WebView *)webView didCreateJavaScriptContext:(JSContext *)context forFrame:(WebFrame *)frame{
context[@"window"][@"open"] = ^(id url){
        NSLog(@"url to load: %@", url);
    };
}

これにより、要求を処理することができましたが、追加の WebView を作成するという厄介な必要はありませんでした。

于 2015-08-24T03:41:49.810 に答える
0

説明:

window.open を介して JavaScript から作成されたウィンドウは、createWebViewWithRequest を通過します。すべての window.open 呼び出しは createWebViewWithRequest: になり、null 要求が発生し、後でその WebView の場所が変更されます。

詳細については、WebKit メーリング リストのこの古い投稿を参照してください。

于 2014-11-07T04:58:05.260 に答える