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
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
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.
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!
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% 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:
Das ist es ziemlich. Hier ist der Code für meine Klasse. Kopfzeile:
%Vor%Implementierung:
%Vor%Lizenziert als Apache 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.
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%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 .
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.
Damit konnte ich die Anfrage bearbeiten, ohne dass es nötig war, zusätzliche WebViews zu erstellen.
Tags und Links objective-c macos cocoa webkit