While working on the Mac Catalyst version of my iOS app, I noticed something interesting. I have a UITextView
with the allowsEditingTextAttributes
property enabled. When running the app on a Mac, the context menu that appears when right-clicking inside the UITextField
includes the menu item "Import from iPhone or iPad". That brings up a menu with 3 options each for my iPhone and iPad that I happen to connected to my Mac recently. There options include "Take Photo", "Scan Documents", and "Add Sketch".
I created a brand new iOS app project and simply added a UITextView to the main view controller. After setting allowsEditingTextAttributes
to true
, it shows the same behavior.
Some questions:
-
Is this documented anywhere? I'm guessing this is related to Continuity Camera in some way. But there's no mention of this anywhere that I've seen so far.
-
How can I prevent this menu from appearing? Nothing related to these menus comes through the
canPerformAction(_:withSender:)
method. And nothing related to these menus is part of the menu item array sent to theUITextViewDelegate textView(_:editMenuForTextIn:suggestedActions:)
method. I need to remove this menu in my app because while I support some text attributes (bold, italic, underline), I do not want to allow pictures to be added. -
Does anything else in iOS under Mac Catalyst automatically get similar support? If so, what?
Success! (mostly).
I finally found a way to remove the "Take a Photo", "Scan Documents", and "Add Sketch" menus. The solution doesn't result in any stack traces either which is nice. The only minor piece left is that this solution does leave the grayed out device name menu item in the context menu. And if there is more than one device, the "Import from iPhone or iPad" menu still appears but only with the grayed out device names.
Here's the code that removes the three unwanted menu items (for each device):
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == Selector(("importFromDevice:")) {
// sender will be an NSMenuItem. There will be one each for the 3 menus we are trying to hide
if let menu = sender as? NSObject, menu.responds(to: Selector(("setHidden:"))) {
menu.setValue(true, forKey: "hidden")
}
return false
}
return super.canPerformAction(action, withSender: sender)
}
Add this to any view controller that has a UITextView
to eliminate the 3 context menu options. Or create a custom subclass of UITextView
and put the code in there. Then use the custom text view class anywhere you don't want these menus.