1

I have code to copy the numbers from the Label.

I have a button for copying, how can I make it so that when I click on it open the menu that is in the photo and I could click the copy button?

enter image description here

@IBAction func copybutton(_ sender: UIButton) {
    UIPasteboard.general.string = displayResultLabel.text
}
KVL
  • 37
  • 8

2 Answers2

1

With a meager amount of information from your question, hopefully I understand the problem correctly.

I have created an example that has a UIViewController with a UILabel and a UIButton.

Whenever the button is pressed, the screen will display an action sheet menu with three buttons (Copy, Paste, View Memory).

And when the Copy button in the action sheet is pressed, we will copy the text of the label.

enter image description here

This is the code:

Note:

UILabel named displayResultLabel.

UIButton's action named showActionSheetButtonAction.

class ViewController: UIViewController {

    @IBOutlet weak var displayResultLabel: UILabel!

    @IBAction func showActionSheetButtonAction(_ sender: UIButton) {
        let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        actionSheetController.addAction(
            UIAlertAction(title: "Copy", style: .default, handler: { [weak self] _ in
                guard let strongSelf = self else { return }

                UIPasteboard.general.string = strongSelf.displayResultLabel.text
            })
        )

        actionSheetController.addAction(
            UIAlertAction(title: "Paste", style: .default, handler: { _ in
                // Where to handle when the Paste button is pressed
            })
        )

        actionSheetController.addAction(
            UIAlertAction(title: "View Memory", style: .default, handler: { _ in
                // Where to handle when the View Memory button is pressed
            })
        )

        actionSheetController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

        present(actionSheetController, animated: true, completion: nil)
    }
}
Anh Pham
  • 2,108
  • 9
  • 18
  • 29
0

You need subclass the UILabel, and change some default things to achieve this, first you need to set userInteractionEnable = true, is false by default in UILabel and you need also override the property canBecomeFirstResponder which is also false by default after that you can show the menu becoming the label firstResponder and using the UIMenuController with longPressGestureRecognizer, class full code is here

Use this UILabel subclass

import UIKit

class ContextMenuLabel: UILabel {

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

    override func awakeFromNib() {
        super.awakeFromNib()
        self.isUserInteractionEnabled = true
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.showContextMenu))
        self.addGestureRecognizer(longPressGesture)
    }

    func showContextMenu()
    {
        self.becomeFirstResponder()
        UIMenuController.shared.setTargetRect(self.frame, in: self.superview!)
        let itemCopy = UIMenuItem(title: "Copy", action: #selector(self.copyAction))
        UIMenuController.shared.arrowDirection = .down
        UIMenuController.shared.menuItems = [itemCopy]
        UIMenuController.shared.setMenuVisible(true, animated: true)

        debugPrint(UIMenuController.shared.menuFrame)
    }

    func copyAction()
    {
        UIPasteboard.general.string = self.text
    }

    override var canBecomeFirstResponder: Bool{
        get{
            return true
        }
    }

}

Result

enter image description here

Hope this helps

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
  • Hi. I'm using your code and so far I get the copy menu. However, I'm trying to copy the message on a label in a tableView and the text from the label is being filled out from my database. When I paste what I just copied, I just get the name of the subclass. How can I make the text that is being copied be the string I'm getting from the database? – Ximena Flores de la Tijera Jan 21 '21 at 19:40
  • @XimenaFloresdelaTijera try debugPrint your label.text – Reinier Melian Jan 21 '21 at 19:52
  • You mean in the func copyAction() { UIPasteboard.general.string = self.text }? Or in the label within the tableviewcell? – Ximena Flores de la Tijera Jan 21 '21 at 23:33
  • Ok, for TableViewCells, is different @XimenaFloresdelaTijera check this answer https://stackoverflow.com/questions/12290828/how-to-show-a-custom-uimenuitem-for-a-uitableviewcell, you need to implement some UITableViewDelegate methods – Reinier Melian Jan 22 '21 at 05:33
  • Hi. I actually tried that answer and it didn't work. I was wondering if maybe this might be the issue. Cause the copying is working just fine, the problem is in the paste part of the solution. Not sure how to apply this to your subclass though. I believe the problem might be in the UIPasteboard.general.string -- https://stackoverflow.com/questions/24670290/how-to-copy-text-to-clipboard-pasteboard-with-swift/24670971#24670971 – Ximena Flores de la Tijera Jan 25 '21 at 15:58
  • @XimenaFloresdelaTijera I had used this answer https://stackoverflow.com/questions/12290828/how-to-show-a-custom-uimenuitem-for-a-uitableviewcell with good results – Reinier Melian Jan 25 '21 at 16:28
  • really? which of the two answers? the one with 51 votes or the one with 8? – Ximena Flores de la Tijera Jan 25 '21 at 16:33
  • @XimenaFloresdelaTijera I will put my answer there updated ok? only for copy – Reinier Melian Jan 25 '21 at 16:37
  • @XimenaFloresdelaTijera check this and let me know https://stackoverflow.com/a/65888995/6190582 – Reinier Melian Jan 25 '21 at 16:52