How can I react meaningfully to a changeAttributes: delegation pass-through from WebView?

后端 未结 2 1790
萌比男神i
萌比男神i 2021-02-15 17:22

WebView supports, through the WebEditingDelegate, a mechanism for the delegate to implement custom behavior for a variety of actions the WebView<

相关标签:
2条回答
  • 2021-02-15 17:37

    Have you looked at the source code?

    WebHTMLView.mm

    I don't see how -changeAttributes: is calling -webView:doCommandBySelector:, as within this class it's only called inside its own -doCommandBySelector: method.

    - (void)changeAttributes:(id)sender
    {
        [self _applyStyleToSelection:[self _styleForAttributeChange:sender] withUndoAction:EditActionChangeAttributes];
    }
    
    
    - (void)doCommandBySelector:(SEL)aSelector
    {
    …
        if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:aSelector] && coreFrame) {
    …
    }
    

    Also, why can't you subclass WebHTMLView? Is it because of the Mac App Store restrictions on API? Does WebKit count as private? I thought it was Open Source.

    -Wil

    0 讨论(0)
  • 2021-02-15 17:40

    This is an evil one. A suitably evil pair of actions (neither of them particularly clean or ideal) would be:

    1. Do some inline assembler to look back up the stack to read the sender argument from the caller's stack (or the caller's caller, as the case should be). This of course assumes that the sender is placed on the stack and not in %eax when the call to WebHTMLView was made. That will always apply to PowerPC code however, so it's likely a non-starter there.

    2. Put a category on WebHTMLView with a method named something like __my_evil_hacky_nasty_ugly_changeAttributes_thing: and at runtime use method_exchangeImplementations() from the ObjC runtime to swap your category's implementation with theirs. Your method becomes changeAttributes: and theirs becomes __my_evil_hacky_nasty_ugly_changeAttributes_thing:, which you can then call to pass on the original call.

    As I said, neither is particularly ideal, but the second has the advantage of full runtime support (i.e. the runtime is explicitly designed to let you do this), and since you're looking up the class and methods at runtime, it's failure-tolerant. Failure in this case gets you back to square one however.

    Really it needs a bug logged against WebKit to have them pass on the sender to make it meaningful at all. Your overridden version could potentially look for a method -(BOOL)webView:(WebView*)webView doCommandBySelector:(SEL)selector sender:(id)sender and call that if found, otherwise just call through to the original method. This is what Apple's code should be doing, TBH.

    0 讨论(0)
提交回复
热议问题