我如何有意义地对changeAttributes做出反应:从WebView传递委托?

dan*_*ass 8 fonts cocoa webkit

WebView通过WebEditingDelegate一种机制,支持代理为WebView(或私有WebHTMLView)接收的各种动作实现自定义行为.当一个动作,如:

-(void)changeAttributes:(id)sender
Run Code Online (Sandbox Code Playgroud)

收到后WebHTMLView,它被传递给委托方法:

-(BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)command
Run Code Online (Sandbox Code Playgroud)

不幸的是,该机制没有规定sender在原始行动方法中传送" ".

对于绝大多数动作,发送者并不重要,但是对于changeAttributes和changeFont,例如,合同要求sender接收者调用" "以便例如convertAttributes:或者convertFont:.

对于这种changeFont情况,事实证明,呼叫[[NSFontManager sharedFontManager] convertFont:]是足够的,因为巧合的是这是发送者.

在这种changeAttributes情况下,特别是当删除线被改变时,发送者可以是私人类" NSFontEffectsBox",其可能对应于负责改变删除线/等设置的字体面板的子部分.

不幸的是,调用[[NSFontManager sharedFontManager] convertAttributes:]不会获得预期的属性更改.这使得有兴趣有意义地实现这种方法的代表有点困惑:

  1. WebKit不传达发件人,因此代表不能进行合同[sender convertAttributes:]调用.

  2. changeAttributes:调用被发送到私有WebKit类,该类WebHTMLView不能被子类化,例如,自定义其行为changeAttributes:.

  3. changeAttributes:呼叫的发送方NSFontEffectsBox是私有类,不能访问,例如[NSFontEffectsBox sharedFontEffectsBox].

简而言之:似乎有没有办法一个开发商有意义重写的行为changeAttributes:WebView.

有任何想法吗?

Jim*_*vey 4

这是一种邪恶的行为。一对适当邪恶的行为(它们都不是特别干净或理想的)将是:

  1. 执行一些内联​​汇编程序来查找堆栈,以从调用者的堆栈(或调用者的调用者,视情况而定)中读取发送者参数。当然,这假设发送者被放置在堆栈上,而不是在%eax调用时放置在堆栈上WebHTMLView。然而,这将始终适用于 PowerPC 代码,因此它可能是一个行不通的人。

  2. WebHTMLView使用名为类似名称的方法放置一个类别__my_evil_hacky_nasty_ugly_changeAttributes_thing:,并在运行时使用 ObjC 运行时中的 method_exchangeImplementations() 将您的类别的实现与他们的实现交换。你的方法变成了,changeAttributes:他们的方法变成了__my_evil_hacky_nasty_ugly_changeAttributes_thing:,然后你可以调用它来传递原始调用。

正如我所说,两者都不是特别理想,但第二个具有完整运行时支持的优势(即运行时明确设计为让您执行此操作),并且由于您在运行时查找类和方法,所以它是失败的 -宽容。然而,在这种情况下失败会让你回到原点。

实际上,它需要针对 WebKit 记录一个错误,让它们传递给发件人,使其变得有意义。您的重写版本可能会查找方法-(BOOL)webView:(WebView*)webView doCommandBySelector:(SEL)selector sender:(id)sender并在找到时调用该方法,否则只需调用原始方法。老实说,这就是苹果代码应该做的事情。