WebView
通过WebEditingDelegate
支持委托机制为WebView
(或私有WebHTMLView
)收到的各种操作实现自定义行为的机制。当一个动作,如:
-(void)changeAttributes:(id)sender
在WebHTMLView
中收到,它将传递给委托方法:
-(BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)command
不幸的是,该机制不提供原始行动方法中“sender
”的传达。
对于绝大多数操作,发件人并不重要,但是对于changeAttributes和changeFont,例如,合同要求收件人调用“sender
”以便例如convertAttributes:
或convertFont:
。
对于changeFont
案例,事实证明,调用[[NSFontManager sharedFontManager] convertFont:]
就足够了,因为巧合的是这就是发件人。
在changeAttributes
案例中,特别是当删除线被更改时,发件人可能是私人类“NSFontEffectsBox
”,可能对应于负责更改删除线/的字体面板的子部分等设置。
不幸的是,调用[[NSFontManager sharedFontManager] convertAttributes:]
无法获得预期的属性更改。这使得有兴趣有意义地实现这种方法的代表有点困惑:
WebKit不传达发件人,因此代表无法进行合同[sender convertAttributes:]
来电。
changeAttributes:
调用被发送到私有WebKit类WebHTMLView
,该类不能被子类化,例如,自定义changeAttributes:
的行为。
changeAttributes:
来电的发件人NSFontEffectsBox
是私人类,无法访问,例如为[NSFontEffectsBox sharedFontEffectsBox]
。
简而言之:开发人员似乎没有办法有意义地覆盖changeAttributes:
的{{1}}行为。
有什么想法吗?
答案 0 :(得分:4)
这是一个邪恶的。适当的邪恶行为(他们都不特别干净或理想)将是:
做一些内联汇编程序来查看堆栈以从调用者的堆栈(或调用者的调用者,视情况应该)读取sender参数。当然,这假定发件人被放置在堆栈上,而不是在%eax
调用WebHTMLView
时。这将始终适用于PowerPC代码,因此它很可能是非启动器。
使用名为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
,如果找到则调用该方法,否则只需调用原始方法。这就是Apple的代码应该做的事情,TBH。
答案 1 :(得分:3)
你看过源代码了吗?
我没有看到-changeAttributes:
如何调用-webView:doCommandBySelector:
,因为在此类中,它仅在其自己的-doCommandBySelector:
方法中调用。
- (void)changeAttributes:(id)sender
{
[self _applyStyleToSelection:[self _styleForAttributeChange:sender] withUndoAction:EditActionChangeAttributes];
}
- (void)doCommandBySelector:(SEL)aSelector
{
…
if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector] && coreFrame) {
…
}
另外,为什么不能将WebHTMLView子类化?是因为Mac App Store对API的限制吗? WebKit是否算作私有?我以为是开源。
-Wil