在WKWebView中处理粘贴内容 [英] Manipulate paste content in 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)
但是我有两个问题:
-
userContentController:didReceiveScriptMessage:
从未被调用 - 我不知道如何截取粘贴的代码并将其替换为其他内容
userContentController:didReceiveScriptMessage:
is never called- 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屋!