web-dev-qa-db-fra.com

Comment désactiver le collage dans un TextField dans Swift?

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?

39
Eliko

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:

  • Accédez à votre storyboard
  • Cliquez sur le TextField cible
  • Sélectionnez Inspecteur d'identité (le 3ème)
  • Modifiez la classe en tant que CustomUITextField

Un aperçu rapide est fourni ci-dessous.

enter image description here

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 ?

44
TimeString

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
}
46
Andrey Gordeev

Pour Swift3

UIResponder​Standard​Edit​Actions 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)
    }
}
20
Nikhil Manapure

Détails

  • Xcode 9.1, Swift 4
  • Xcode 10.2 (10E125), Swift 5

Solution 1

// class TextField: UITextField
extension UITextField {

    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
    }
}

Utilisation de la solution 1

let textField = UITextField(frame: CGRect(x: 50, y: 120, width: 200, height: 50))
textField.borderStyle = .roundedRect
view.addSubview(textField)

Solution 2

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)
    }
}

Utilisation de la solution 2

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]
17
Vasily Bodnarchuk

Vous pouvez créer une extension pour UITextField et remplacer canPerformAction:

override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        return (action != "paste:") 
}
4
zaltzy

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(_:))
}
4
Harikant Amipara

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
}
4
dede.exe

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)} )
}
3
Leo Dabus
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
    }
}
2
Tejash Joshi

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)
    }
}
1
Pramod More

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)
    }
0
waleed alghamdi

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
}
0
Renish Dadhaniya