J'ai un TextField
avec un pavé numérique et la fonction ne fonctionne que si elle contient des chiffres.
La seule option pour que l'utilisateur plante l'application est de coller des lettres dans TextField
et de cliquer sur OK.
Comment désactiver le collage dans TextField?
Je suis d'accord avec Leonardo Savio Dabus, si j'étais vous, j'utiliserais la vérification des chaînes et donnerais juste un avertissement, cela rend les choses plus faciles. MAIS, si la désactivation de l'option de collage est une fonctionnalité sophistiquée que vous souhaitez vraiment intégrer à votre application, vous devez faire plus de travail. Je vais fournir les étapes ci-dessous.
Étape 1: Vous devez créer une autre classe qui étend le UITextField
. Dans cet exemple, j'ai fait mon CustomUITextField
.
import Foundation
import UIKit // don't forget this
class CustomUITextField: UITextField {
override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
if action == "paste:" {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Étape 2: Câblez le storyboard avec votre ViewController. Vous devez déclarer un IBOutlet
comme dans le cas normal:
@IBOutlet var textFieldA: CustomUITextField?
Câblez le cercle à côté du @IBOutlet
au textField dans le storyboard. ALORS, c'est important et facile à ignorer:
Un aperçu rapide est fourni ci-dessous.
Voilà, j'espère que cela fonctionne.
Crédit:
Référence principalement de https://teamtreehouse.com/forum/disable-paste-in-uitextfielduitextview-Swift
Si vous voulez en savoir plus sur le comportement de la méthode canPerformAction
, il s'agit de la version objective-C, mais les concepts sont partagés: Comment puis-je détecter qu'un utilisateur a appuyé sur un bouton de mise en forme dans un UIMenuController ?
Pour Swift il est changé en:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
return false
}
return true
}
Pour Swift3
UIResponderStandardEditActions
a été ajouté récemment (iOS 10.0+) à travers lequel nous pouvons vérifier en toute sécurité si l'action est "coller" ou non.
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)
}
}
// 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)
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 {
var allowedActions: [ResponderStandardEditActions] = [] {
didSet {
if !allowedActions.isEmpty && !notAllowedActions.isEmpty {
notAllowedActions = []
}
}
}
var notAllowedActions: [ResponderStandardEditActions] = [] {
didSet {
if !allowedActions.isEmpty && !notAllowedActions.isEmpty {
allowedActions = []
}
}
}
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if !allowedActions.isEmpty {
return allowedActions.map{ $0.selector }.contains(action)
}
if !notAllowedActions.isEmpty {
return !notAllowedActions.map{ $0.selector }.contains(action)
}
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.allowedActions = [.copy, .cut]
//textField.notAllowedActions = [.copy, .cut]
Vous pouvez créer une extension pour UITextField
et remplacer canPerformAction
:
override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
return (action != "paste:")
}
Swift 4.1 ce code fonctionne bien avec ViewController.
1) Désactivez toutes les options (copier, coller, supprimer ..... etc.)
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
2) Activer une option particulière (sélectionner, sélectionner Tout ... etc)
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.select(_:)) || action == #selector(UIResponderStandardEditActions.selectAll(_:))
}
Dans la version réelle Swift (2.2 passe à 3.0), ce code de fonction doit être refactorisé pour:
override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
if action == #selector(NSObject.copy(_:)) || action == #selector(NSObject.paste(_:)) {
return false
}
return true
}
Vous pouvez simplement joindre une IBAction à vos événements envoyés (modification modifiée) de votre champ de texte pour filtrer les non-nombres de votre chaîne lorsque vous tapez comme suit:
@IBAction func changedTextAction(sender: UITextField) {
sender.text = String(Array(sender.text).map{String($0)}.filter{ $0.toInt() != nil }.map{Character($0)} )
}
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
}
}
J'ai créé une classe personnalisée pour textField. J'ai traité le cas lorsque vous souhaitez activer/désactiver des actions sur le champ de texte. Vous pouvez personnaliser le code selon vos besoins. Définissez isActionsEnabled true/false pour activer/désactiver les actions sur le champ de texte.
Je préfère utiliser
return super.canPerformAction (action, withSender: sender)
au lieu de
retourner vrai
car retourner true peut provoquer un crash dans certains cas.
Voici mon 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)
}
}
Petite modification avec un code car lorsque vous essayez d'utiliser une fonction comme cut ou une autre, l'application se bloque. Le code suivant testé sur Swift 3 et fonctionne très bien
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)
}
Si vous voulez ouvrir le sélecteur de dates ou la vue Sélecteur sur TEXTFIELD, cliquez sur le code ci-dessous.
Ajoutez ci-dessous deux méthodes dans votre classe.
//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)
}
// DOIT implémenter
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}