Stack Overflow Asked by Eliko on November 26, 2020
I’ve got a TextField
with a numberPad
and the function runs only if it contains numbers.
The user will crash the app if they paste letters in the TextField
and click OK.
How can I disable pasting in the TextField
?
I agree with Leonardo Savio Dabus, if I were you I'd use string checking and just give out a warning, it makes things easier. BUT, if disabling paste option is a fancy feature you really want to put into your app, then you need to do more work. I'll provide the steps below.
Step 1: You need to create another class which extends the UITextField
. In this example, I made my CustomUITextField
.
import Foundation
import UIKit //Don't forget this
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)
}
}
Step 2: Wire the storyboard with your ViewController. You need to declare an IBOutlet
as in normal case:
@IBOutlet var textFieldA: CustomUITextField?
Wire the circle next to the @IBOutlet
to the TextField
in the storyboard. THEN, this is important and easy to be ignored:
TextField
CustomUITextField
Quick snapshot is provided below.
That's it, hope this works.
Credit:
If you want to know more about the behavior of canPerformAction
method, though it's an Objective-C version, the concepts are shared here.
Correct answer by TimeString on November 26, 2020
I did use this code. This is working.
override func canPerformAction(_ action: Selector, withSender sender: Any?) Bool {
if YOURTEXTFIELD.isFirstResponder {
DispatchQueue.main.async(execute: {
(sender as? UIMenuController)?.setMenuVisible(false, animated: false)
})
return false
}
return super.canPerformAction(action, withSender: sender)
}
Answered by Sameen Ahmad on November 26, 2020
Swift 5
If you want to block paste action from every text field in your app
extension UITextField {
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.paste(_:)) ?
false : super.canPerformAction(action, withSender: sender)
}
}
EDIT
If you want to block the paste action for text fields that have pickers as input view, add a guard
like the following:
extension UITextField {
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
guard inputView != nil else { return super.canPerformAction(action, withSender: sender) }
return action == #selector(UIResponderStandardEditActions.paste(_:)) ?
false : super.canPerformAction(action, withSender: sender)
}
}
Warning: the second solution will allow the user to paste on numeric fields.
Answered by Matias Jurfest on November 26, 2020
If you want to Open Date Picker or Picker view on TEXTFIELD click then below code work.
Add below two methods in your class.
//Hide Menu View
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if YOURTEXTFIELD.isFirstResponder {
DispatchQueue.main.async(execute: {
(sender as? UIMenuController)?.setMenuVisible(false, animated: false)
})
return false
}
return super.canPerformAction(action, withSender: sender)
}
//MUST Implement
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
Answered by Renish Dadhaniya on November 26, 2020
Swift 4.1 this code is working fine with ViewController.
1) Disable all option (copy, paste, delete.....etc)
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
2) Enable particular option (select, selectAll... etc)
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.select(_:)) || action == #selector(UIResponderStandardEditActions.selectAll(_:))
}
Answered by Harikant Amipara on November 26, 2020
I have created a custom class for textField. I have handled the case when you want to enable/disable actions on textfield. You can customize the code as per your requirement. Set isActionsEnabled true/false for enable/disable actions on textfield.
Prefer to use
return super.canPerformAction(action, withSender: sender)
instead of
return true
because returning true might cause a crash in some cases.
Here is my code,
open class MyTextFieldEffect : UITextField {
var isActionsEnabled = true {
didSet {
reloadInputViews()
}
}
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
/* disable particular actions
if (action == #selector(paste(_:)) || action == #selector(copy(_:)) || action == #selector(select(_:)) || action == #selector(cut(_:)) || action == #selector(delete(_:)) || action == #selector(replace(_:withText:)) || action == #selector(select(_:)) || action == #selector(selectAll(_:)) || action == #selector(insertText(_:)) || action == #selector(draw(_:))) && !isActionsEnabled {
return false
}
return super.canPerformAction(action, withSender: sender)
*/
//disable all actions
if !isActionsEnabled {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Answered by Pramod More on November 26, 2020
class CustomUITextField: UITextField {
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(cut(_:)) ||
action == #selector(copy(_:)) ||
action == #selector(UIResponderStandardEditActions.paste(_:)) ||
action == #selector(UIResponderStandardEditActions.select(_:)) ||
action == #selector(UIResponderStandardEditActions.selectAll(_:)) ||
action == #selector(UIResponderStandardEditActions.delete(_:)) ||
action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight(_:)) ||
action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleBoldface(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleItalics(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleUnderline(_:)) ||
action == #selector(UIResponderStandardEditActions.increaseSize(_:)) ||
action == #selector(UIResponderStandardEditActions.decreaseSize(_:))
{
return false
};
return true
}
}
Answered by Tejash Joshi on November 26, 2020
// class TextField: UITextField
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
}
}
let textField = UITextField(frame: CGRect(x: 50, y: 120, width: 200, height: 50))
textField.borderStyle = .roundedRect
view.addSubview(textField)
import UIKit
// MARK: Enable/Disable textfield longpress actions
enum ResponderStandardEditActions {
case cut, copy, paste, select, selectAll, delete
case makeTextWritingDirectionLeftToRight, makeTextWritingDirectionRightToLeft
case toggleBoldface, toggleItalics, toggleUnderline
case increaseSize, decreaseSize
var selector: Selector {
switch self {
case .cut:
return #selector(UIResponderStandardEditActions.cut)
case .copy:
return #selector(UIResponderStandardEditActions.copy)
case .paste:
return #selector(UIResponderStandardEditActions.paste)
case .select:
return #selector(UIResponderStandardEditActions.select)
case .selectAll:
return #selector(UIResponderStandardEditActions.selectAll)
case .delete:
return #selector(UIResponderStandardEditActions.delete)
case .makeTextWritingDirectionLeftToRight:
return #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight)
case .makeTextWritingDirectionRightToLeft:
return #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft)
case .toggleBoldface:
return #selector(UIResponderStandardEditActions.toggleBoldface)
case .toggleItalics:
return #selector(UIResponderStandardEditActions.toggleItalics)
case .toggleUnderline:
return #selector(UIResponderStandardEditActions.toggleUnderline)
case .increaseSize:
return #selector(UIResponderStandardEditActions.increaseSize)
case .decreaseSize:
return #selector(UIResponderStandardEditActions.decreaseSize)
}
}
}
class TextField: UITextField {
private var editActions: [ResponderStandardEditActions: Bool]?
private var filterEditActions: [ResponderStandardEditActions: Bool]?
func setEditActions(only actions: [ResponderStandardEditActions]) {
if self.editActions == nil { self.editActions = [:] }
filterEditActions = nil
actions.forEach { self.editActions?[$0] = true }
}
func addToCurrentEditActions(actions: [ResponderStandardEditActions]) {
if self.filterEditActions == nil { self.filterEditActions = [:] }
editActions = nil
actions.forEach { self.filterEditActions?[$0] = true }
}
private func filterEditActions(actions: [ResponderStandardEditActions], allowed: Bool) {
if self.filterEditActions == nil { self.filterEditActions = [:] }
editActions = nil
actions.forEach { self.filterEditActions?[$0] = allowed }
}
func filterEditActions(notAllowed: [ResponderStandardEditActions]) {
filterEditActions(actions: notAllowed, allowed: false)
}
func resetEditActions() { editActions = nil }
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if let actions = editActions {
for _action in actions where _action.key.selector == action { return _action.value }
return false
}
if let actions = filterEditActions {
for _action in actions where _action.key.selector == action { return _action.value }
}
return super.canPerformAction(action, withSender: sender)
}
}
let textField = TextField(frame: CGRect(x: 50, y: 50, width: 200, height: 50))
textField.borderStyle = .roundedRect
view.addSubview(textField)
textField.setEditActions(only: [.copy, .cut, .paste])
//textField.filterEditActions(notAllowed: [.copy, .cut, .paste])
//textField.addToCurrentEditActions(actions: [.paste])
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
addTextField(y: 50)
addTextField(y: 100).setEditActions(only: [.copy, .cut, .paste])
addTextField(y: 150).filterEditActions(notAllowed: [.copy, .cut, .paste])
}
@discardableResult func addTextField(y: CGFloat) -> TextField {
let textField = TextField(frame: CGRect(x: 50, y: y, width: 200, height: 34))
textField.borderStyle = .roundedRect
textField.text = "Text"
view.addSubview(textField)
return textField
}
}
Answered by Vasily Bodnarchuk on November 26, 2020
Small edit with a code because when you try to use any function like cut or another one the app will crash . The following code tested on swift 3 and working very well
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
Answered by waleed alghamdi on November 26, 2020
For Swift 5
UIResponderStandardEditActions
has been added recently (iOS 10.0+) through which we can safely check if action is "paste" or not.
import UIKit
class NMTextField: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.paste(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Answered by Nikhil Manapure on November 26, 2020
For Swift 3 it's changed to:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
return false
}
return true
}
Answered by Andrey Gordeev on November 26, 2020
In the actual swift version(2.2 going to 3.0) this function code must be refactored to:
override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
if action == #selector(NSObject.copy(_:)) || action == #selector(NSObject.paste(_:)) {
return false
}
return true
}
Answered by dede.exe on November 26, 2020
You can create an extension for UITextField
and override canPerformAction
:
override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
return (action != "paste:")
}
Answered by zaltzy on November 26, 2020
You can just attach an IBAction to your Sent Events (editing changed) of your textfield to filter non numbers out of your string as you type as follow:
@IBAction func changedTextAction(_ sender: UITextField) {
sender.text = sender.text?.filter(.isWholeNumber)
}
This will allow the user to paste into the field but it will filter all non digits from the string.
Answered by Leo Dabus on November 26, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP