/ UIMenuController

使用 UIMenuController 的前提

一种取舍

给 View 加长按手势弹出自定义 Items 的 Menu 大概如下:

let longPress = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
textContentTextView.addGestureRecognizer(longPress)

func handleLongPress(longPress: UILongPressGestureRecognizer) {
    if longPress.state == .Began {
        if let view = longPress.view, superview = view.superview {
            let menu = UIMenuController.sharedMenuController()
            let loveItem = UIMenuItem(title: "Love", action:"loveAction")
            menu.menuItems = [loveItem]
            menu.setTargetRect(view.frame, inView: superview)
            menu.setMenuVisible(true, animated: true)
        }
    }
}

但 UIMenuController 必须要在 View canBecomeFirstResponder 的前提下才能弹出。而对于自定义的 UITextView,若我们需要禁止选择(但不禁止点击链接),那要重载canBecomeFirstResponder()为:

override func canBecomeFirstResponder() -> Bool {
    return false
}

由此,我们就不能在这个自定义的 TextView 上通过加长按手势进而弹出 UIMenuController,得自己写一个自定义的 Menu 了。

来自 @Naituw 的 Workaround

如果不想自己画 Menu 那么可以将 UITextView 嵌套进一个 UIView 里,把 UILongPressGestureRecognizer 添加到 UIView 上。

但是由此有不少需要自己来定制的部分。

首先给容器 UIView 添加一个手势,handleLongPress 的处理和上面一样即可。

let longPress = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")

testView.addGestureRecognizer(longPress)

longPress.delegate = self

通过设置 Gesture 的 Delegate 来使 UITextView 和 UIView 上的 UILongPressGestureRecognizer 都可以被识别出来。

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
  return true      
}

此时你还需要 Subclass UIView,override 里面的两个方法

override func canBecomeFirstResponder() -> Bool {
  return true
}
    
override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
   if action == "loveAction" {
        return true
   } else {
        return false
   }       
}

在 canPerformAction 里,对我们设定的 action return true

由此就可以避免自己绘制 UIMenu。

使用 UIMenuController 的前提
Share this