为什么在调用menuItem的动作时会再次调用PerformAction?

时间:2018-05-08 03:33:13

标签: ios swift

下面是我的代码,我发现当点击菜单" pasteAndGo"时,会打印两个日志字符串:1。粘贴并显示2.paste并单击。我的要求是当显示菜单时,记录"粘贴并显示"显示。单击它时,记录"粘贴并单击"显示。

class MyTextField: UITextField {

      private func Init() {
          let menuController: UIMenuController = UIMenuController.shared
          menuController.isMenuVisible = true
          let pasteAndGoMenuItem: UIMenuItem = UIMenuItem(title: "pasteAndGo", action: #selector(pasteAndGo(sender:)))

          let myMenuItems: NSArray = [pasteAndGoMenuItem]
          menuController.menuItems = myMenuItems as? [UIMenuItem]
      }

      @objc private func pasteAndGo(sender: UIMenuItem) {
          Print("paste and go clicked")
      }

      override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
          let pasteboard = UIPasteboard.general

          if action == #selector(pasteAndGo) {
              if pasteboard.url != nil {
              Print("paste and go show")
                  return true
          } else {
              return false
          }
        }

        return super.canPerformAction(action, withSender: sender)
    }
}

1 个答案:

答案 0 :(得分:0)

您的代码按实施方式运行:

  • 在您按 pasteAndGo 菜单项的瞬间,UIKit框架调用canPerformAction询问是否允许执行操作。在这里,您打印“粘贴并去展示”
  • 由于您返回true,您的操作pasteAndGo(sender:)会被执行并打印“粘贴并点击”

要对显示的菜单项做出反应,您必须使用UIMenuControllerWillShowMenu通知注册到通知中心,如下所示:

// create a property 
var token:NSObjectProtocol?

// then add observer  
self.token = NotificationCenter.default.addObserver(forName: Notification.Name.UIMenuControllerWillShowMenu,
                                           object: nil,
                                           queue: OperationQueue.main)
    { _ in
        print ("paste and go show")
    }

并且在您的viewcontroller被解雇后不要忘记取消订阅(NotificationCenter.default.removeObserver)。

if let t = self.token {
    NSNotificationCenter.defaultCenter().removeObserver(t)
}

更新

你也可以在Init

中这样做(没有属性)
// in Init
var token = NotificationCenter.default.addObserver(forName: Notification.Name.UIMenuControllerWillShowMenu,
                                           object: nil,
                                           queue: OperationQueue.main)
    { _ in
        print ("paste and go show")
        NSNotificationCenter.defaultCenter().removeObserver(token)
    }