Cocoa / WebKit, mit "window.open ()" JavaScript-Links öffnen in einer Instanz von Safari

7

Ich erstelle eine wirklich einfache Cocoa-Anwendung mit WebKit, um darin eine Flash / Silverlight-Anwendung anzuzeigen. Sehr einfach, keine Absicht, selbst ein Browser zu sein.

Bisher war es mir möglich, grundlegende HTML-Links ( <a href="..." /> ) in einer neuen Instanz von Safari mit

zu öffnen %Vor%

Jetzt ist mein Problem, einen Link in einer neuen Instanz von Safari zu öffnen, wenn window.open() in JavaScript verwendet wird. Ich "denke" (und damit habe ich den Code gehackt und bin mir nicht sicher, ob ich das tatsächlich getan habe oder nicht). Ich habe diese Art von Arbeit gemacht, indem ich das% cowe% des WebViews gesetzt und sein

implementiert habe %Vor%

Delegiertenmethode. Dies führte jedoch zu unberechenbarem Verhalten.

Also die einfache Frage, was muss ich tun, damit wenn policyDelegate aufgerufen wird, der Link in einer neuen Instanz von Safari geöffnet wird.

Danke

Wichtiger Punkt, ich bin normalerweise ein .NET Entwickler und habe erst seit ein paar Tagen mit Cocoa / WebKit gearbeitet.

    
FireWire 06.11.2008, 21:53
quelle

7 Antworten

9

Ich habe letzte Nacht Fortschritte gemacht und einen Teil meines Problems festgehalten.

Ich verwende bereits webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: und ich habe es mit Anchor-Tags arbeiten lassen, aber die Methode scheint nie aufgerufen zu werden, wenn JavaScript aufgerufen wird.

Wenn window.open() jedoch aufgerufen wird webView:createWebViewWithRequest:request wird aufgerufen, habe ich versucht, das Öffnen des Fensters in Safari zu erzwingen, die Anfrage ist jedoch immer null. Also kann ich die URL nie auslesen.

Ich habe ein wenig herumgesucht, und das scheint ein bekanntes " Fehlverhalten " zu sein, aber ich war nicht in der Lage, einen Weg zu finden, um es zu umgehen.

Was ich verstehe createWebViewWithRequest gibt Ihnen die Möglichkeit, die neue Webansicht zu erstellen, die angeforderte URL wird dann an das neue webView gesendet, um geladen zu werden. Dies ist die beste Erklärung, die ich bisher finden konnte.

Obwohl viele Leute auf dieses Problem hingewiesen haben, habe ich noch keine Lösung gefunden, die meinen Bedürfnissen entspricht. Ich werde versuchen, noch ein wenig tiefer in die decidePolicyForNewWindowAction einzutauchen.

Danke!

    
FireWire 07.11.2008 16:02
quelle
6

Nun, ich gehe damit um, indem ich eine Dummy-WebView erstelle, die ihren frameLoad-Delegaten auf eine benutzerdefinierte Klasse setzt, die

behandelt %Vor%

und öffnet dort ein neues Fenster.

code:

%Vor%

und NewWindowHandler:

%Vor%     
Yoni Shalom 04.02.2009 10:20
quelle
4

Es scheint einen Fehler mit webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: zu geben, da die Anfrage immer nil ist, aber es gibt eine robuste Lösung, die sowohl mit normalen target="_blank" -Links als auch mit Javascript-Einsen funktioniert.

Im Grunde benutze ich ein anderes ephemeres WebView, um die neue Seite zu laden. Ähnlich wie Yoni Shalom, aber mit etwas mehr syntaktischem Zucker.

Um es zu verwenden, setze zuerst ein Delegate-Objekt für dein WebView, in diesem Fall setze ich mich selbst als Delegat:

%Vor%

Dann implementieren Sie einfach die Methode webView:createWebViewWithRequest: delegate und verwenden Sie meine blockbasierte API, um etwas zu tun, wenn eine neue Seite geladen wird. In diesem Fall öffne ich die Seite in einem externen Browser:

%Vor%

Das ist es ziemlich. Hier ist der Code für meine Klasse. Kopfzeile:

%Vor%

Implementierung:

%Vor%

Lizenziert als Apache 2.

    
lms 13.03.2013 10:17
quelle
2

Sie erwähnen nicht, welche Art von unberechenbarem Verhalten Sie sehen. Eine schnelle Möglichkeit besteht darin, dass Sie beim Implementieren der Delegate-Methode vergessen haben, dem Webview mitzuteilen, dass Sie den Klick ignorieren, indem Sie die ignore-Methode der WebPolicyDecisionListener , das an Ihren Delegaten übergeben wurde, was die Dinge in einen merkwürdigen Zustand versetzt haben könnte.

Wenn das nicht das Problem ist, wie viel Kontrolle haben Sie dann über den Inhalt, den Sie anzeigen? Der Policy-Delegat bietet einfache Mechanismen zum Filtern aller Ressourcenladungen (wie Sie festgestellt haben), und alle neuen Fenster werden über webView: decidePolicyForNewWindowAction: request: newFrameName: decisionListener: . Alle Aufrufe von window.open sollten durch dieses Fenster geleitet werden, ebenso wie alles, was ein neues Fenster auslöst.

Wenn sich andere Fenster öffnen, die Sie in Ihrer App behalten möchten, werden Sie etwas mehr Arbeit erledigen. Eines der Argumente, das an den Delegaten übergeben wird, ist ein Wörterbuch, das Informationen über die Veranstaltung. Stellen Sie sicher, dass der WebActionElementKey ein Wörterbuch enthält, das eine Anzahl von Details , einschließlich des ursprünglichen dom-Inhalts des Links. Wenn Sie dort herumstochern wollen, können Sie sich das eigentliche DOM-Element ansehen und den Text der href überprüfen, um zu sehen, ob es mit window.open beginnt. Das ist ein bisschen schwer, aber wenn Sie feinkörnige Kontrolle wollen, wird es Ihnen geben.

    
Louis Gerbarg 07.11.2008 10:30
quelle
2

Beim Lesen aller Posts, habe ich meine einfache Lösung gefunden, alle Funcs sind in der gleichen Klasse, hier ist es, öffnet einen Link mit Browser.

%Vor%     
KeranMarinov 09.12.2013 21:42
quelle
0

Erläuterung:

Windows, das mit JavaScript über window.open erstellt wurde, muss createWebViewWithRequest durchlaufen. Alle Aufrufe von window.open führen zu einem createWebViewWithRequest: mit einer NULL-Anfrage und später einem Standortwechsel in diesem WebView.

Weitere Informationen finden Sie in diesem alten Post auf der WebKit-Mailingliste .

    
user1985657 07.11.2014 04:58
quelle
0

Als Alternative zum Zurückgeben eines neuen WebView und Warten auf den Aufruf seiner loadRequest: -Methode habe ich die Funktion window.open im JSContext von WebView überschrieben:

Zuerst habe ich meinen Controller als WebFrameLoadDelegate des WebView festgelegt:

%Vor%

Dann habe ich in der Delegate-Methode die window.open -Funktion überschrieben und kann stattdessen die URL dort verarbeiten.

%Vor%

Damit konnte ich die Anfrage bearbeiten, ohne dass es nötig war, zusätzliche WebViews zu erstellen.

    
adam.wulf 24.08.2015 03:41
quelle

Tags und Links