如何从Objective-C的WKWebView中获取选定的文本 [英] How do I get the selected text from a WKWebView from objective-C

查看:650
本文介绍了如何从Objective-C的WKWebView中获取选定的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WKWebView.

I have a WKWebView.

当用户右键单击它时,我可以在我的Objective-C方法中自定义上下文菜单.仅当用户在WKWebView中选择了一些文本时,我才想添加菜单项.当然,我稍后需要检索选定的文本以进行处理.

When the user right-clicks on it, I can customize a contextual menu in my objective-c method. I'd like to add a menu item only if the user has selected some text in the WKWebView. And of course I'll need to retrieve the selected text later on to process it.

如何从Objective-c的WKWebView中检索选择,确保它只是文本并获取该文本?

How can I retrieve the selection from a WKWebView from objective-c, make sure it is only text and get that text ?

谢谢

推荐答案

这是我设法做到的方式.这不是一个完美的解决方案,但是足够好.

Here is how I managed to do that. Not a perfect solution, but good enough.

一般说明

似乎WKWebView内部发生的任何事情都必须使用Javascript进行管理.苹果提供了一个在Javascript世界和Objective-C(或Swift)世界之间交换信息的框架.此框架基于一些消息,这些消息是从Javascript世界发送的,并通过可以安装在WKWebView中的消息处理程序捕获在Objective-C(或Swift)世界中的.

It seems that anything that happens inside the WKWebView must be managed in Javascript. And Apple provides a framework for exchanging information between the Javascript world and the Objective-C (or Swift) world. This framework is based on some messages being sent from the Javascript world and caught in the Objective-C (or Swift) world via a message handler that can be installed in the WKWebView.

第一步-安装消息处理程序

在Objective-C(或Swift)世界中,定义一个对象,该对象将负责从Javascript世界中接收消息.我为此使用了视图控制器.下面的代码将视图控制器安装为用户内容控制器",它将接收名为"newSelectionDetected"的事件,这些事件可以从Javascipts发送

In the objective-C (or Swift) world define an object that will be responsible for receiving the messages from the Javascript world. I used my view controller for that. The code below installs the view controller as a "user content controller" that will receive events named "newSelectionDetected" that can be sent from 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"的消息发送新选择

This Javascript will detect selection change, and send the new selection through a message named "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:

and the 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世界.

Now, every time we have a mouse up or a key up in the WKWebView, the selection (possibly empty) will be caught and send to the Objective-C world through the message.

我们只需要在视图控制器中使用一个处理程序来处理该消息

We just need a handler in the view controller to handle that message

- (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存储在此属性中.

I made a class which inherits from WKWebView, and has a NSString property 'selectedText'. So what I do in this handler, is to store the received NSString in this property.

第四步-更新上下文菜单

在我的WKWebView的子类中,如果selectedText不为空,我只是重写willOpenMenu:WithEvent:方法以添加菜单项.

In my daughter class of WKWebView, I just override the willOpenMenu:WithEvent: method to add a menu item if selectedText is not empty.

- (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,我将覆盖它.

Now why isn't that ideal ? Well if your web page already sets onmouseup or onkeyup, I override that.

但是正如我所说,对我来说足够好了.

But as I said, good enough for me.

我在javascript中添加了document.oncontextmenu行,它解决了我有时遇到的奇怪选择行为.

Edit : I added the document.oncontextmenu line in the javascript, that solved the strange selection behavior I sometimes had.

这篇关于如何从Objective-C的WKWebView中获取选定的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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