Wie kann ich sinnvoll auf eine changeAttributes reagieren: Delegierungs-Pass-Through von WebView?

8

WebView unterstützt über den WebEditingDelegate einen Mechanismus, mit dem der Delegierte benutzerdefiniertes Verhalten für eine Vielzahl von Aktionen implementieren kann, die der WebView (oder der private WebHTMLView ) empfängt. Wenn eine Aktion wie:

%Vor%

wird in WebHTMLView empfangen und an die Delegate-Methode übergeben:

%Vor%

Leider bietet der Mechanismus nicht die Übertragung von " sender " in der ursprünglichen Aktionsmethode.

Für die überwiegende Mehrheit von Aktionen ist der Absender unwichtig, aber für changeAttributes und changeFont zum Beispiel erfordert der Vertrag, dass " sender " vom Empfänger aufgerufen wird, um z. convertAttributes: oder convertFont: .

Für den Fall changeFont stellt sich heraus, dass das Aufrufen von [[NSFontManager sharedFontManager] convertFont:] ausreicht, da dies zufälligerweise der Absender ist.

Im Fall changeAttributes , insbesondere wenn die Durchstreichung geändert wird, kann der Absender eine private Klasse " NSFontEffectsBox " sein, die vermutlich dem Unterabschnitt des Schriftfelds entspricht, das für die Änderung der Einstellungen von strikethrough / etc verantwortlich ist / p>

Leider ruft der Aufruf von [[NSFontManager sharedFontManager] convertAttributes:] NICHT die erwarteten Attributänderungen auf. Dies lässt einen Delegierten, der daran interessiert ist, diese Methode in einem kleinen Rätsel sinnvoll umzusetzen:

  1. WebKit übermittelt den Absender nicht, sodass der Delegierte den vertraglichen [sender convertAttributes:] -Aufruf nicht durchführen kann.

  2. Der changeAttributes: -Aufruf wird an eine private WebKit-Klasse, WebHTMLView , gesendet, die nicht unterklassifiziert werden kann, z. B. um das Verhalten von changeAttributes: anzupassen.

  3. Der Absender für den changeAttributes: -Aufruf, NSFontEffectsBox , ist eine private Klasse, auf die z. B. nicht zugegriffen werden kann. als [NSFontEffectsBox sharedFontEffectsBox] .

Kurz gesagt: Es scheint keinen Entwickler zu geben, der das Verhalten von changeAttributes: für WebView sinnvoll übersteuern könnte.

Irgendwelche Ideen?

    
danielpunkass 10.12.2010, 16:56
quelle

2 Antworten

4

Das ist ein böser. Ein angemessenes böses Paar von Handlungen (von denen keines besonders sauber oder ideal ist) wäre:

  1. Machen Sie einen Inline-Assembler, um sich den Stack anzusehen, um das Absenderargument vom Stack des Aufrufers (oder gegebenenfalls vom Aufrufer des Aufrufers) zu lesen. Dies setzt natürlich voraus, dass der Sender auf dem Stack platziert wird und nicht in %eax , wenn der Aufruf von WebHTMLView erfolgt. Das wird jedoch immer für PowerPC-Code gelten, daher ist es wahrscheinlich ein Nicht-Starter dort.

  2. Fügen Sie eine Kategorie in WebHTMLView mit einer Methode mit dem Namen __my_evil_hacky_nasty_ugly_changeAttributes_thing: hinzu und verwenden Sie zur Laufzeit die Methode method_exchangeImplementations () aus der ObjC-Laufzeitumgebung, um die Implementierung Ihrer Kategorie mit ihren zu tauschen. Ihre Methode wird changeAttributes: und ihre wird __my_evil_hacky_nasty_ugly_changeAttributes_thing: , die Sie dann aufrufen können, um den ursprünglichen Aufruf zu übergeben.

Wie gesagt, beides ist nicht besonders ideal, aber das zweite hat den Vorteil der vollen Laufzeitunterstützung (dh die Laufzeit ist explizit dafür ausgelegt, dies zu ermöglichen), und da Sie zur Laufzeit die Klasse und Methoden nachschlagen, es ist fehlertolerant. Das Scheitern in diesem Fall bringt Sie jedoch auf Platz eins zurück.

Wirklich es braucht einen Fehler, der gegen WebKit geloggt wird, um sie den Absender weiterzugeben, um ihn überhaupt sinnvoll zu machen. Ihre überschriebene Version könnte möglicherweise nach einer Methode -(BOOL)webView:(WebView*)webView doCommandBySelector:(SEL)selector sender:(id)sender suchen und diese aufrufen, wenn sie gefunden wird, andernfalls rufen Sie einfach die ursprüngliche Methode auf. Das sollte Apples Code tun, TBH.

    
Jim Dovey 10.12.2010 17:25
quelle
3

Haben Sie sich den Quellcode angesehen?

WebHTMLView.mm

Ich sehe nicht, wie -changeAttributes: -webView:doCommandBySelector: aufruft, da es innerhalb dieser Klasse nur innerhalb seiner eigenen -doCommandBySelector: -Methode aufgerufen wird.

%Vor%

Warum können Sie auch WebHTMLView nicht ableiten? Liegt es an den Beschränkungen des Mac App Store für die API? Ist WebKit als privat zu betrachten? Ich dachte, es wäre Open Source.

-Wil

    
Wil Shipley 10.12.2010 17:36
quelle

Tags und Links