こういうの |
調べたところ、touchesBeganとcanPerformActionをオーバーライドすればカスタマイズできそうとのことなのでこんな感じにしてみました。
protocol CustomedMenuTextViewDelegate: class {
func customedMenu1(selectedText: String)
func customedMenu2(selectedText: String)
func customedMenu3(selectedText: String)
}
class CustomedMenuTextView: UITextView {
weak var customedMenuDelegate: CustomedMenuTextViewDelegate?
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
let menuController = UIMenuController.shared
menuController.setTargetRect(CGRect.zero, in: self)
menuController.arrowDirection = .down
let menuItems = [
UIMenuItem.init(title: "Menu1", action: #selector(menu1Selected(sender: ))),
UIMenuItem.init(title: "Menu2", action: #selector(menu2Selected(sender: ))),
UIMenuItem.init(title: "Menu3", action: #selector(menu3Selected(sender: ))),
]
menuController.menuItems = menuItems
menuController.setMenuVisible(true, animated: true)
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(menu1Selected(sender: )) ||
action == #selector(menu2Selected(sender: )) ||
action == #selector(menu3Selected(sender: )) {
return true
}
return false
}
// MARK: - ACTION EVENT METHOD
@objc private func menu1Selected(sender: Any) {
guard let _ = sender as? UIMenuController else {
print("error1")
return
}
let selectedText = self.text(in: self.selectedTextRange!)!
if let d = customedMenuDelegate {
d.customedMenu1(selectedText: selectedText) //選択された文字列を返す
}
}
@objc private func menu2Selected(sender: Any) {
guard let _ = sender as? UIMenuController else {
print("error2")
return
}
let selectedText = self.text(in: self.selectedTextRange!)!
if let d = customedMenuDelegate {
d.customedMenu2(selectedText: selectedText) //選択された文字列を返す
}
}
@objc private func menu3Selected(sender: Any) {
guard let _ = sender as? UIMenuController else {
print("error3")
return
}
let selectedText = self.text(in: self.selectedTextRange!)!
if let d = customedMenuDelegate {
d.customedMenu3(selectedText: selectedText) //選択された文字列を返す
}
}
}
呼び出す側はこうします。
class ViewController: UIViewController, CustomedMenuTextViewDelegate {
@IBOutlet weak var textView: CustomedMenuTextView!
// MARK: - UIViewController: RESPONDING TO VIEW EVENTS
override func viewDidLoad() {
super.viewDidLoad()
textView.isEditable = false
textView.customedMenuDelegate = self
}
// MARK: - UIViewController: HANDLING MEMORY WARNINGS
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - METHODS FOR CustomedMenuTextViewDelegate
func customedMenu1(selectedText: String) {
print("Menu1: selected text = " + selectedText)
}
func customedMenu2(selectedText: String) {
print("Menu2: selected text = " + selectedText)
}
func customedMenu3(selectedText: String) {
print("Menu3: selected text = " + selectedText)
}
}
もう少し汎用性を持たせたいところですが、とりあえず動作するようなので我慢します。
こうなりました |
Appleによる正規の方法ではなさそうです。
WKWebView(deprecatedだけどUIWebViewでもいいけど)でも、同じことをしたかったのですが、この方法ではダメでした。残念。
良い方法ないですかね?
「使ってみた(App Extension編) その1」に続きます。