【问题标题】:Manipulate paste content in WKWebView在 WKWebView 中操作粘贴内容
【发布时间】:2020-07-22 05:47:18
【问题描述】:

我需要处理粘贴到 WKWebView(来自任何来源)中的文本,该文本运行可能需要一些时间的异步操作。

我最初的想法是使用 Javascript 和 WKWebView 配置来获取onpaste 事件:

WKUserContentController *wkUController = [[WKUserContentController alloc] init];

NSString *pasteJSSource = @"document.addEventListener('onpaste', function(){ window.webkit.messageHandlers.ComposerListener.postMessage('onpaste happened!'); })";

WKUserScript *pasteScript = [[WKUserScript alloc] initWithSource:pasteJSSource injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly: NO];

[wkUController addScriptMessageHandler:self name:@"ComposerListener"];

[wkUController addUserScript:pasteScript];

webViewConfiguration.userContentController = wkUController;

然后我的班级实现WKScriptMessageHandler

#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    NSLog(@"message: %@", message.body);
}

(忽略Obj-c,swift也可以)

但是我有两个问题:

  1. userContentController:didReceiveScriptMessage: 永远不会被调用
  2. 我不知道如何截取粘贴的代码并用不同的东西替换它

关于如何解决这个问题的任何想法(即使没有我显然不知道的 JS :P )? 谢谢。

【问题讨论】:

    标签: javascript ios wkwebview wkwebviewconfiguration


    【解决方案1】:

    为了后代:

    我确信存在使用 JS 的方法来做到这一点并且更清洁,但我设法使用方法 swizzling 实现了结果:

    //Method Swizzling
    UIView *webContentView = self.webView.contentView;
    if(webContentView != nil)
    {
        //Paste:
        NSError *error;
        [webContentView swizzleMethod:@selector(paste:) withSelector:@selector(my_paste:) error:&error];
        if(error != nil)
        {
            NSLog("Failed to swizzle 'paste:' into WKContentView: %@, error);
            NSAssert(false, error);
        }
    
        ...
    }
    

    contentView 在哪里:

    - (UIView *)contentView
    {
        return [self subviewWithClassName:@"WKContentView"];
    }
    

    方法my_paste:需要是UIResponder的一部分(由私有WKContentView实现)

    #pragma mark - Method Swizzling UIResponder
    
    @interface UIResponder (WebComposerSwizzling)
    
    - (void)my_paste:(id)sender;
    #define original_paste my_paste
    
    @end
    
    @implementation UIResponder (WebComposerSwizzling)
    
    - (void)my_paste:(id)sender
    {
        MailComposerViewController* strongComposer = sCurrentComposer;
        if (strongComposer)
            [strongComposer manipulatePasteboard:nil];
        [self original_paste:sender];
    }
    
    @end
    

    请注意,sCurrentComposer 是我的 ViewController 中的静态变量

    __weak MailComposerViewController* sCurrentComposer;
    

    各种实用程序:

    UIView+SubviewSearch

    import UIKit
    
    extension UIView {
    
        /// Find a subview corresponding to the className parameter, recursively.
        @objc public func subviewWithClassName(_ className: String) -> UIView? {
            if NSStringFromClass(type(of: self)) == className {
                return self
            } else {
                for subview in subviews {
                    return subview.subviewWithClassName(className)
                }
            }
            return nil
        }
    }
    

    NSObject+Swizzling

    import Foundation
    
    extension NSObject {
    
        enum NSObjectSwizzlingError: Error {
            case originalSelectorNotFound
        }
    
        @objc public func swizzleMethod(_ currentSelector: Selector, withSelector newSelector: Selector) throws {
            if let currentMethod = self.instanceMethod(for: currentSelector),
                let newMethod = self.instanceMethod(for:newSelector) {
                method_exchangeImplementations(currentMethod, newMethod)
            } else {
                throw NSObjectSwizzlingError.originalSelectorNotFound
            }
        }
    
        @objc public func instanceMethod(for selector: Selector) -> Method? {
            let classType: AnyClass! = object_getClass(self)
            return class_getInstanceMethod(classType, selector)
        }
    }
    

    (我对 Swift OBJ-C 组合感到抱歉)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      相关资源
      最近更新 更多