2
votes

i've a web view with displayed a pdf file. As a standard for the web view the user can select a text and perform standard operation like copy, cut. I need to add a custom UIMenuController for show custom action. I do not understand how to copy the selected text in the standard UIPasteboard and pass to my custom selector. I've tried to use

[[UIApplication sharedApplication] sendAction:@selector(copy:) to:nil from:self forEvent:nil];

in method and i'm able to copy the selected text but i do not understand how to come back this value to my method.

This is my code (simplified) In the view did load i've added one observer for UIPasteboardChangedNotification for perform my selector myCopy:

- (void)viewDidLoad
{
[super viewDidLoad];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myCopy:) name:UIPasteboardChangedNotification object:nil];

UIMenuItem *schedaMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"POPSCHEDA",nil) action:@selector(copyScheda:)];
UIMenuItem *istruzionetMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"POPISTR",nil) action:@selector(copyIstruzione:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:MenuItem1,MenuItem2,nil]];

}

-(void)myCopy:(id)sender {
  UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  NSString* copyCode = pasteboard.string;
  //perform the necessary action
 }

 -(void)copyScheda:(id)sender {
   UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
   NSString* copyCode = pasteboard.string;
   //perform the necessary action
 }

 -(void)copyIstruzione:(id)sender {
   UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
   NSString* copyCode = pasteboard.string;
   //perform the necessary action
 }

Thank you for your help and for your time!

1

1 Answers

1
votes

If I'm understanding your question correctly, then you are trying to grab the text that is currently selected, copy it to the pasteboard when the user taps your custom item, and then do something with that selected/copied text?

If so, I think this should work for you, at least it's working for me in Swift 4.

First, in viewDidLoad, setup your custom menu item

let customMenuItem = UIMenuItem(title: "Foo Bar", action: #selector(ViewController.customMenuTapped))
UIMenuController.shared.menuItems = [customMenuItem]
UIMenuController.shared.update()

Then, still in viewDidLoad set yourself up as an observer to UIPasteboardChanged

NotificationCenter.default.addObserver(self, selector: #selector(displaySelectecText), name: NSNotification.Name.UIPasteboardChanged, object: nil)

Then create your function that responds to the customMenuItem, in my example here it's customMenuTapped(), and you basically send the copy action to the responder chain to handle it.

@objc func customMenuTapped() {
    UIApplication.shared.sendAction(#selector(copy(_:)), to: nil, from: self, for: nil)
}

Since you've registered yourself as a listener, when the copy action is done, your other function will get called, mine is displaySelectecText()

@objc func displaySelectedText() {
    let copiedText = UIPasteboard.general.string ?? ""
    let alertView = UIAlertController(title: "Selected Text", message: copiedText, preferredStyle: .alert)
    alertView.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    present(alertView, animated: true, completion: nil)
}

In this example, I am just displaying the text in an alert view for simplicity.

Here is the complete code:

import UIKit
import WebKit

class ViewController: UIViewController {

    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        loadWebView()
        setupCustomMenu()
        setupListener()
    }

    func loadWebView() {
        let url = URL(string: "http://www.google.com")
        let request = URLRequest(url: url!)
        webView.load(request)
    }

    func setupCustomMenu() {
        let customMenuItem = UIMenuItem(title: "Foo Bar", action:
            #selector(ViewController.customMenuTapped))
        UIMenuController.shared.menuItems = [customMenuItem]
        UIMenuController.shared.update()
    }

    func setupListener() {
        NotificationCenter.default.addObserver(self, selector: #selector(displaySelectedText), name: NSNotification.Name.UIPasteboardChanged, object: nil)
    }

    @objc func customMenuTapped() {
        UIApplication.shared.sendAction(#selector(copy(_:)), to: nil, from: self, for: nil)
    }

    @objc func displaySelectedText() {
        let copiedText = UIPasteboard.general.string ?? ""
        let alertView = UIAlertController(title: "Selected Text", message: copiedText, preferredStyle: .alert)
        alertView.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertView, animated: true, completion: nil)
    }

}

And here is a demo

enter image description here