How to remove the default UIMenuItem from the UIMenuController in iOS? - iphone

I want to remove some default UIMenuItem objects like "Cut", "Copy", etc, from the UIMenuController.
How to do that ?
Thanks.

Subclass the view that's presenting the menu (eg. UIWebView, UITextView) and override -canPerformAction:withSender: to return NO for the menu items you don't want to appear.
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == #selector(copy:)) {
return NO;
}
else {
return [super canPerformAction:action withSender:sender];
}
}

class TextView: UITextView {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)){
return true
}
else{
return false
}
}
}
In Swift 4 ,
As Peter Stuart said:
Subclass the view that's presenting the menu (eg. UITextView)
then override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool
return false for the menu items you don't want to appear.

Related

Make custom UITextView selection bar with only translate in Swift 5

Is there a way to only allow the new translate option of ios15 in a custom UITextView? See the following picture to know what I mean with translate option:
Translate option
I know about the canPerformAction method but there is no translate option:
class CustomUITextField: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}

How to disable the copy paste functionality in SkyFloatingLabelTextField in swift?

I am using the SkyFloatingLabelTextField class for UITextfield,How can I disable the Copy and paste functionality on this textfiled.
Use this technique for custom textField
class SkyFloatingLabelTextField: UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Create a custom class inherited from SkyFloatingLabelTextField class and then assign.
class FloatingTextField: SkyFloatingLabelTextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) ||
action == #selector(UIResponderStandardEditActions.copy(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
If you want for the whole project and all textfield add this extension.
extension SkyFloatingLabelTextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) ||
action == #selector(UIResponderStandardEditActions.copy(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}

Hiding Copy, Look Up, Share... in WKWebView UIMenuController

I am working on a PR for react-native-webview to add custom menu items to the RNCWebView (which is a subclass of WKWebView). It works in that it adds the additional options but "Copy | Look Up | Share..." always appear. Even if canPerformAction returns NO for every action (note that canPerformAction is not returning true/YES for copy)
I've come across so many other posts such as:
WKWebView and UIMenuController
Removing Copy, Look Up, and Share from UIMenuController
Custom Cut, Copy & Paste operations for WKWebView
And countless other ones that just suggest using CSS to hide the entire menu. I am not trying to hide the whole menu, but just "Copy, Look Up and Share" while letting my custom ones remain while using WKWebView.
My thought was that there was some other class up the responder chain that is still setting them to true, but I've tried extending and overriding as many as I know about and still those options show up:
extension UIView {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UITextView {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UIImageView{
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UIScrollView{
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UISlider{
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UIWebView{
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
#objc private extension UIResponder {
func swizzle_canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
None of that works. Those three options still appear no matter what. Does anyone know what class could responding and adding these options? This seems like a common question but all the posts I find are either unanswered or wildly out of date.
// WKWebView subclass //
import WebKit
import UIKit
class MyWebView: WKWebView {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
// View controller //
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
// MARK: - Variables
var helloMenu = UIMenuItem()
// MARK: - IBOutlet
#IBOutlet weak var myWebView: MyWebView!
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
myWebView.navigationDelegate = self
helloMenu = UIMenuItem(title: "Hello", action: #selector(sayHello))
UIMenuController.shared.menuItems = [helloMenu]
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let urlStr = "https://www.google.com/"
if let url = URL(string: urlStr) {
let request = URLRequest(url: url)
myWebView.load(request)
}
}
// MARK: - Custom menu
#objc func sayHello() {
print("Hello")
}
}
First, sub-class WKWebView, removing all menu items.
Make an IBOutlet object of WKWebView and change its class name.
Add your custom menu item to your view controller.

Is there a preferred technique to prohibit pasting into a UITextField?

I've read several offered solutions for different versions of Swift.
What I cannot see is how to implement the extensions--if that's even the best way to go about it.
I'm sure there is an obvious method here that was expected to be known first, but I'm not seeing it. I've added this extension and none of my text fields are affected.
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
}
}
You can not override a class method using an extension.
from the docs "NOTE Extensions can add new functionality to a type, but they cannot override existing functionality."
What you need is to subclass UITextField and override your methods there:
To only disable paste functionality:
class TextField: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Usage:
let textField = TextField(frame: CGRect(x: 50, y: 120, width: 200, height: 50))
textField.borderStyle = .roundedRect
view.addSubview(textField)
To allow only copy and cut:
class TextField: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
[#selector(UIResponderStandardEditActions.cut),
#selector(UIResponderStandardEditActions.copy)].contains(action)
}
}
Siwft 5
// class TextField: UITextField
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
}
}

numeric keyboard resigns to normal key board in swift

I have a normal set up for a textfield with numberpad and the dismiss keyboard and resignFirstResponder actions in place, but when I tap on the background the numeric keyboard changes to the normal keyboard and then when I tap the background again the keyboard dismisses - STRANGE! How can I dismiss the numeric keyboard with one tap to the background?
self.textField.delegate = self
textField.keyboardType = UIKeyboardType.DecimalPad
#IBAction func tapBackground(sender: AnyObject) {
view.endEditing(true)
}
#IBAction func viewTapped(sender: AnyObject) {
textField.resignFirstResponder()
}
Try following this may help you :)
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: "handleTapGesture:")
tap.delegate = self
self.view.addGestureRecognizer(tap)
}
// MARK: - UITapGestureRecognizer
func handleTapGesture(gesture : UITapGestureRecognizer) {
self.view.endEditing(true)
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
{
return true
}