在WKWebView中处理粘贴内容 [英] Manipulate paste content in WKWebView

查看:526
本文介绍了在WKWebView中处理粘贴内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要操纵粘贴到WKWebView中的文本(来自任何来源),以运行异步操作,这可能需要一些时间.

I need to manipulate the text that is pasted into a WKWebView (from any source) running an asynchronous operation that can take some time.

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

My original idea was to use Javascript and the WKWebView configuration in order to get the onpaste event:

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,也可以很快)

(Ignore Obj-c, swift is ok too)

但是我有两个问题:

  1. userContentController:didReceiveScriptMessage:从未被调用
  2. 我不知道如何截取粘贴的代码并将其替换为其他内容
  1. userContentController:didReceiveScriptMessage: is never called
  2. I don't know how to intercept the pasted code and replace it with something different

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

Any idea on how to solve this (even without JS that I don't obviously know :P )? Thanks.

推荐答案

出于礼节:

我敢肯定有一种使用JS来做到这一点的方法,并且它更干净,但是我设法通过swizzling方法实现了结果:

I'm sure there a way to do this using JS exists and is cleaner but I managed to achieve the result using method 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所在的位置:

Where the contentView is:

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

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

The method my_paste: need to be part of UIResponder (that is implemented by the private 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中的静态变量

Note that sCurrentComposer is a static variable in my ViewController

__weak MailComposerViewController* sCurrentComposer;


各种实用程序:


The various utilities:

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组合感到抱歉)

(I'm sorry about the Swift <> OBJ-C mix)

这篇关于在WKWebView中处理粘贴内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆