我有一个WKWebView。
当用户右键单击它时,我可以在objective-c方法中自定义上下文菜单。我想仅在用户在WKWebView中选择了一些文本时才添加菜单项。当然,我需要稍后检索所选文本以进行处理。
如何从objective-c中检索WKWebView中的选择,确保它只是文本并获取该文本?
由于
答案 0 :(得分:2)
这是我设法做到的。这不是一个完美的解决方案,但是足够好。
一般说明
似乎WKWebView内部发生的任何事情都必须使用Javascript进行管理。苹果提供了一个在Javascript世界和Objective-C(或Swift)世界之间交换信息的框架。此框架基于一些消息,这些消息是从Javascript世界发送的,并通过可安装在WKWebView中的消息处理程序捕获到Objective-C(或Swift)世界中。
第一步-安装消息处理程序
在Objective-C(或Swift)世界中,定义一个对象,该对象将负责从Javascript世界中接收消息。我为此使用了视图控制器。下面的代码将视图控制器安装为“用户内容控制器”,它将接收名为“ newSelectionDetected”的事件,这些事件可以从Javascipts发送。
- (void)viewDidLoad
{
[super viewDidLoad];
// Add self as scriptMessageHandler of the webView
WKUserContentController *controller = self.webView.configuration.userContentController ;
[controller addScriptMessageHandler:self
name:@"newSelectionDetected"] ;
... the rest will come further down...
第二步-在视图中安装Javascript
此Javascript将检测选择更改,并通过名为“ newSelectionDetected”的消息发送新选择
- (void) viewDidLoad
{
...See first part up there...
NSURL *scriptURL = .. URL to file DetectSelection.js...
NSString *scriptString = [NSString stringWithContentsOfURL:scriptURL
encoding:NSUTF8StringEncoding
error:NULL] ;
WKUserScript *script = [[WKUserScript alloc] initWithSource:scriptString
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES] ;
[controller addUserScript:script] ;
}
和Javascript:
function getSelectionAndSendMessage()
{
var txt = document.getSelection().toString() ;
window.webkit.messageHandlers.newSelectionDetected.postMessage(txt) ;
}
document.onmouseup = getSelectionAndSendMessage ;
document.onkeyup = getSelectionAndSendMessage ;
document.oncontextmenu = getSelectionAndSendMessage ;
第三步-接收和处理事件
现在,每当我们在WKWebView中按下鼠标或按下某个键时,所选内容(可能为空)就会被捕获并通过消息发送到Objective-C世界。
我们只需要在视图控制器中使用一个处理程序来处理该消息
- (void) userContentController:(WKUserContentController*)userContentController
didReceiveScriptMessage:(WKScriptMessage*)message
{
// A new selected text has been received
if ([message.body isKindOfClass:[NSString class]])
{
...Do whatever you want with message.body which is an NSString...
}
}
我制作了一个继承自WKWebView的类,并具有NSString属性'selectedText'。因此,我在此处理程序中所做的就是将接收到的NSString存储在此属性中。
第四步-更新上下文菜单
在WKWebView的子类中,如果selectedText不为空,我只是重写willOpenMenu:WithEvent:方法以添加菜单项。
- (void) willOpenMenu:(NSMenu*)menu withEvent:(NSEvent*)event
{
if ([self.selectedText length]>0)
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"That works !!!"
action:@selector(myAction:)
keyEquivalent:@""] ;
item.target = self ;
[menu addItem:item] ;
}
}
- (IBAction) myAction:(id)sender
{
NSLog(@"tadaaaa !!!") ;
}
现在为什么不那么理想?好吧,如果您的网页已经设置了onmouseup或onkeyup,我将覆盖它。
但是正如我所说,对我来说足够好了。
编辑:我在javascript中添加了document.oncontextmenu行,它解决了我有时遇到的奇怪选择行为。
答案 1 :(得分:1)
快速5翻译
webView.configuration.userContentController.add(self, name: "newSelectionDetected")
let scriptString = """
function getSelectionAndSendMessage()
{
var txt = document.getSelection().toString() ;
window.webkit.messageHandlers.newSelectionDetected.postMessage(txt);
}
document.onmouseup = getSelectionAndSendMessage;
document.onkeyup = getSelectionAndSendMessage;
document.oncontextmenu = getSelectionAndSendMessage;
"""
let script = WKUserScript(source: scriptString, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
webView.configuration.userContentController.addUserScript(script)
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// Use message.body here
}
答案 2 :(得分:0)
只需要评估简单的js脚本
NSString *script = @"window.getSelection().toString()";
使用evaluateJavaScript
方法
[wkWebView evaluateJavaScript:script completionHandler:^(NSString *selectedString, NSError *error) {
}];
Swift版本
let script = "window.getSelection().toString()"
wkWebView.evaluateJavaScript(script) { selectedString, error in
}