Le formatage d'un UITextField pour la carte de crédit d'une entrée comme (xxxx xxxx xxxx xxxx)
Je veux formater un UITextField
pour la saisie d'un numéro de carte de crédit telle qu'elle permet uniquement de chiffres pour être inscrit et insère automatiquement des espaces de sorte que le nombre est formaté comme suit:
XXXX XXXX XXXX XXXX
Comment puis-je faire cela?
- Si vous pouvez utiliser des bibliothèques open source, je voudrais vous recommandons vivement de prendre un coup d'oeil à PaymentKit (github.com/stripe/PaymentKit). Ils ont un module de formatage vous pouvez utiliser, et cela fonctionne pour tous les types de cartes (et a un programme de validation ainsi de luhn vérifier et autres joyeusetés).
- intrigante, et peut-être - pour autant que je sache - une meilleure approche de ma réponse, mais je n'ai pas le temps ni l'envie de le regarder (surtout que je n'ai pas de Mac, et je n'ai pas fait de développement iOS en plus d'un an). Si vous avez de l'expérience avec la bibliothèque, puis la rédaction d'une réponse montrant un exemple simple d'utilisation, il serait probablement ont beaucoup plus de valeur pour les futurs lecteurs que juste un commentaire.
- Cette réponse peut vous aider si vous êtes à la recherche pour une approche dynamique. stackoverflow.com/a/38560759/3947151
- Cette question continue d'attirer des réponses de gens qui comptent ils aident en fournissant un plus court, plus simple de répondre que mon (accepté) réponse. Ces réponses sont en effet plus court et plus simple - et comme une conséquence, pas un seul d'entre eux travaille! (Et oui, j'ai personnellement testé tous un seul.) C'est un trompeusement difficile problème, les gens! Si vous allez essayer de fournir une meilleure réponse, à moins de lire la section "Explication" de ma réponse, et beaucoup, beaucoup de commentaires que j'ai laissé en expliquant les moyens des autres implémentations sont brisés, et vérifiez que vous n'êtes pas à défaut de la même manière.
Vous devez vous connecter pour publier un commentaire.
Si vous êtes en utilisant Swift, allez lire mon port de cette réponse rapide 4 et l'utiliser à la place.
Si vous êtes en Objective-C...
Tout d'abord, à votre
UITextFieldDelegate
, l'ajout de ces variables d'instance...... et ces méthodes:
Ensuite, définissez
reformatCardNumber:
être appelé à chaque fois que le champ de texte déclenche unUIControlEventEditingChanged
événement:(Bien sûr, vous aurez besoin de faire cela à un certain moment après votre champ de texte et de son délégué ont été instanciés. Si vous utilisez des storyboards, la
viewDidLoad
méthode de votre vue-contrôleur est un endroit approprié.Quelques Explications
C'est un air faussement compliquée problème. Trois questions importantes qui peuvent ne pas être immédiatement évident (et dont les réponses précédentes ici tous ne parviennent pas à prendre en compte):
Tandis que le
XXXX XXXX XXXX XXXX
format de débit et de crédit, des numéros de carte est le plus commun, il n'est pas le seul. Par exemple, des cartes American Express 15 chiffres généralement écrits enXXXX XXXXXX XXXXX
format, comme ceci:Même les cartes Visa peuvent avoir moins de 16 chiffres, et les cartes Maestro pouvez avoir plus de:
Il y a plus de moyens pour l'utilisateur d'interagir avec un champ de texte que de simplement taper dans de simples caractères à la fin de leur saisie. Vous devez également gérer correctement l'utilisateur d'ajouter des caractères dans le milieu de la chaîne, la suppression de les caractères unique, la suppression de plusieurs caractères sélectionnés, et coller dans de multiples personnages. Certains plus simple/plus naïf des approches à ce problème ne pourront pas gérer certains de ces interactions correctement. Le plus pervers de cas est un utilisateur de coller plusieurs personnages dans le milieu de la chaîne à remplacer les autres personnages, et cette solution est assez générale pour gérer cela.
Vous n'avez pas seulement besoin de reformater le texte du champ de texte correctement une fois que l'utilisateur modifie - vous aussi besoin de la position de la curseur de texte raisonnablement. Naïf approches du problème qui ne prennent pas en compte sera presque certainement finir par faire quelque chose de stupide avec le curseur de texte dans certains cas (comme à la fin du champ de texte lorsque l'utilisateur ajoute un chiffre dans le milieu de celui-ci).
Pour traiter de la question #1, nous utilisons la partielle de cartographie de numéro de carte de préfixes de formats, organisée par L'Baymard Institut à https://baymard.com/checkout-usability/credit-card-patterns. Nous pouvons détecter automatiquement la le fournisseur de la carte à partir du premier couple de chiffres (dans certains cas) en déduire le format et ajuster la mise en forme en conséquence. Grâce à cnotethegr8 pour contribuer à cette idée pour cette réponse.
La plus simple et la meilleure façon de traiter de la question #2 (et la manière utilisée dans le code ci-dessus) est de supprimer tous les espaces et réinsérez-les dans la position correcte à chaque fois que le contenu du champ de texte changements, en épargnant nous le besoin de comprendre à quel type de manipulation de texte (une insertion, de suppression ou de remplacement) est en cours et gérer les possibilités différemment.
Pour traiter de la question #3, nous garder une trace de la façon dont l'indice désiré du curseur change comme nous dépouiller non chiffres, puis insérer des espaces. C'est pourquoi le code plutôt avec beaucoup de détails effectue ces manipulations, caractère par caractère à l'aide de
NSMutableString
, plutôt que d'utiliserNSString
's de la chaîne de méthodes de remplacement.Enfin, il y a un piège, tapie: le retour de
NO
detextField: shouldChangeCharactersInRange: replacementString
sauts de la "coupure" sur le bouton, l'utilisateur obtient quand ils sélectionner du texte dans le champ de texte, c'est pourquoi je ne le fais pas. De retourNO
à partir de cette méthode aboutit à "Couper" tout simplement pas la mise à jour du presse-papiers à tous, et je ne connais aucun correctif ou une solution de contournement. En conséquence, nous avons besoin de faire le reformatage du champ de texte dans unUIControlEventEditingChanged
gestionnaire au lieu de (évidemment) dansshouldChangeCharactersInRange:
lui-même.Heureusement, la UIControl gestionnaires d'événements semblent avoir appelé avant de l'INTERFACE utilisateur les mises à jour se rincé à l'écran, de sorte que cette approche fonctionne très bien.
Il y a aussi tout un tas de mineur questions sur exactement comment le champ de texte doit se comporter qui n'ont pas évident de corriger les réponses:
Probablement la réponse à une de ces questions sera suffisant, mais je liste juste pour préciser qu'il y a effectivement beaucoup de cas particuliers que vous pourriez vouloir penser soigneusement le sujet ici, si vous étiez assez obsessionnel. Dans le code ci-dessus, j'ai ramassé des réponses à ces questions qui semblait raisonnable pour moi. Si vous avez des sentiments forts au sujet de l'un de ces points qui ne sont pas compatible avec la façon dont mon code se comporte, il devrait être assez facile de l'ajuster à vos besoins.
unrecognized selector sent to instance
et un thread problème quand je fais cela. Des idées?targetCursorPosition
au début est cassé. Essayez d'ajouter un Caractère qui n'est pas un Scalaire unicode, comme un emoji. La position du curseur sera inexacte.Vous pouvez probablement optimiser mon code ou il y a peut être un moyen plus facile, mais ce code devrait fonctionner:
Ci-dessous est un travail Swift 4 port de Logicopolis réponse (qui est à son tour une Swift 2 port d'une ancienne version de mon accepté de répondre à en Objective-C) le renforcement de la avec cnotethegr8
s'astuce pour soutenir les cartes Amex et puis encore amélioré pour prendre en charge plusieurs formats de carte. Je suggère à la recherche sur les accepté de répondre si vous ne l'avez pas déjà, car il permet d'expliquer la motivation à l'origine de beaucoup de ce code.
Remarque que le minimum d'une série d'étapes nécessaires pour le voir en action est:
Main.storyboard
, ajouter un Champ de Texte.ViewController
le délégué de la Champ de Texte.ViewController.swift
.IBOutlet
à la Champ de Texte.S'adapter à d'autres situations comme la votre délégué n'étant pas un
ViewController
- est laissé comme exercice pour le lecteur.*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSBigMutableString substringWithRange:]: Range {20, 0} out of bounds; string length 19'
reformatAsCardNumber
va arrêter le plantage survenant. Il n'est pas d'une grande correction, mais il fonctionne.Je pense que c'est la bonne:
if ([string length] == 0) return YES;
Swift 3 solution à l'aide de Fawkes réponse de base.
Ajout de la Carte Amex en charge du format.
Ajouté réforme lorsque le type de la carte a changé.
D'abord faire une nouvelle classe avec ce code:
Dans votre ViewControllerClass ajouter cette fonction
Puis ajoutez la cible à votre textField
Enregistrer une nouvelle variable et envoyé type de carte à
Grâce Fawkes pour son code!
1234 5678 9012
dans mon champ de texte, puis-je placer mon curseur de texte après la9
et frapper la touche retour arrière, le9
est supprimé, mais mon curseur de texte se termine après le0
plutôt que d'après la8
.formattedString.appendFormat("%@-", préfixe) chage de "-" tout autre votre choisir
Encore une autre version de la accepté de répondre à Swift 2...
Vous assurer que vous avez dans votre instance de délégué:
Et également veiller à ce que votre zone de texte appelle reformatAsCardNumber:
Vous champ de texte délégué aurez besoin pour ce faire:
Enfin inclure des méthodes suivantes:
Ici est une Swift version dans le cas où c'est utile pour ceux qui sont encore à la recherche de cette réponse, mais l'utilisation de Swift au lieu d'Objective-C. Les concepts restent les mêmes, peu importe.
Définir la méthode ci-dessous & appel dans UITextfield délégués ou chaque fois que nécessaire
Afin d'atteindre l'objectif de mettre en forme le texte entré dans le champ de cette façon
XXXX XXXX XXXX XXXX est important de garder à l'esprit certaines choses importantes.
A part le fait que la carte bancaire à 16 chiffres d'un numéro séparé tous les quatre chiffres qui est le plus utilisé
format, il y a des cartes avec 15 chiffres (AmEx formaté XXXX XXXXXX XXXXX) et d'autres à 13 chiffres ou même à 19 chiffres (https://en.wikipedia.org/wiki/Payment_card_number
). Autre chose importante que vous devriez considérer est de configurer le champ texte pour autoriser uniquement les chiffres, configurez le type de clavier comme pavé numérique est un bon début, mais il est commode de mettre en œuvre une méthode qui fixent l'entrée.
Un point de départ est de décider quand vous voulez formater le nombre, alors que l'utilisateur est entré dans
le nombre ou lorsque l'utilisateur quitte le champ de texte.
Dans le cas que vous souhaitez formater lorsque l'utilisateur quitte le champ est commode de
utiliser le textFieldDidEndEditing(_:) le délégué de la méthode de prendre le contenu de la zone de texte
et le format.
Dans le cas où vous lorsque l'utilisateur est en entrant le numéro est utile à l'
textField(_:shouldChangeCharactersIn:replacementString:) délégué méthode qui est appelée
chaque fois que le texte actuel modifications.
Dans les deux cas il y a encore un problème, de déterminer qui est le format correct pour le numéro entré, à mon humble avis, et selon tous les numéros que j'ai vu, il y a seulement deux formats: l'Amex format avec 15 chiffres décrit ci-dessus et que le format de groupe numéro de carte de tous les quatre chiffres qui ne se soucient pas de la façon dont beaucoup de chiffres, il y a ce cas comme un générique de la règle, par exemple, une carte à 13 chiffres seront mis en forme XXXXX XXXX XXXX X et à 19 chiffres ressemblera à ceci XXXX XXXX XXXX XXXX XXX, cela fonctionne pour les cas les plus courants (16 chiffres) et pour les autres. Si vous pouviez comprendre comment gérer l'AmEx cas avec le même algorithme ci-dessous jouer avec la magie des nombres.
J'ai utilisé une expression régulière pour s'assurer que 15 chiffres est une carte American express, dans le cas d'autres formats particuliers
Je recommande vivement de les RegEx qui est utile pour identifier l'Émetteur et de comprendre comment de nombreux chiffres devraient être acceptées.
Maintenant, mon approche de swift de la solution avec textFieldDidEndEditing est
et pour shouldChangeCharactersIn:replacementString: une Swift 3.0 à Partir de Jayesh Miruliya Réponse, mettre un séparateur entre le groupe de quatre caractères
Donc je voulais ce avec moins de code, j'ai donc utilisé le code ici et redéfini un peu. J'ai eu deux champs de l'écran, un pour le nombre et l'autre pour la date d'expiration, alors j'en ai fait plus réutilisable.
Swift 3 autre réponse
Swift 3.2
Petite correction dans le @Lucas réponse et le code de travail dans swift 3.2. En supprimant le caractère d'espace automatiquement.
Swift 3 solution basée sur Marque Amery de l'Objective-C solution:
Mettre en œuvre l'action et délégué méthodes:
TextField Délégué de méthodes et d'autres méthodes:
Voici une copie rapide de la accepté de répondre au cas où quelqu'un en a besoin. Il s'agit d'une classe wrapper. Je n'ai pas passé trop de temps sur l'optimisation de lui, mais il est prêt à l'emploi.
previousTextContent
n'importe où, il reçoitnil
(ou, si vous en faites uneString
au lieu d'unString?
, reçoit un peu d'aléatoire d'ordures octets). Cela signifie que si vous débordement de 19 caractères, tout le champ de texte se fait tout simplement effacé (ou peut-être l'application se bloque carrément si vous n'avez pas de chance - mais jusqu'à présent, j'ai toujours vu le blanking).Ici est un Kotlin réponse en dehors de la Marque de Amery
Puis ajouter un texte changer le port d'écoute sur une modification de texte
Ces réponses sont tout simplement beaucoup trop de code pour moi. Voici une solution rapide 2.2.1
Maintenant il suffit de mettre une IBAction dans votre vue-contrôleur:
current
censé être?), ce n'est pas de préserver la position du curseur correctement. par exemple, si j'ai1234 5678
dans le champ de texte et tapez un0
après la4
, je me retrouve avec1234 5678 0
mais avec mon curseur avant le0
j'ai tapé juste, au lieu d'après elle.Veuillez utiliser formulaire simple de credite de la carte
/**
Voir exemple d'utilisation:
### let str = "41111111111111111"
J'espère que cela est utile pour vous.
j'ai modifié @ilesh réponse, de sorte qu'il affiche uniquement les 4 derniers chiffres quelle que soit la longueur est. Également ignorer de l'espace et "-" de la station.
De cette façon, si nous avons un certain nombre avec le format 0000 - 0000 - 0000 - 0000 il affiche XXXX - XXXX - XXXX - 0000
UITextField
s.Trouve un RÉSUMÉ dans Github qui fait exactement ce dont j'ai besoin dans Swift3 (https://gist.github.com/nunogoncalves/6a8b4b21f4f69e0fc050190df96a1e56)
Mis en œuvre par la pratique ->
Fonctionne à merveille dans l'APPLICATION que je suis en train de travailler qui utilise des cartes de crédit.
dans mon cas, nous avons pour le formatage de l'iban. je pense que, le bloc de code ci-dessous vous aider à
Tout d'abord, vérifiez l'utilisateur enterted valeur est valide
Deuxièmement, vous pouvez voir iban formaté méthode comme ci-dessous. Notre iban formaté commencer 2 lettre.
ici est la modification de la réponse de @sleeping_giant pour swift. Cette solution met en forme le texte dans "xxxx-xxxx-xxxx-xxxx-xxxx" format et cesse d'accepter tous les numéros au-delà de cette plage.
Découvrez Cette Solution. J'ai trouvé dans Autorize.net SDK Exemple.
Faire de Votre
UITextField
Type de Clavier àNumeric
.Il Masque Numéros de Carte de Crédit Avec " X " Et Par l'Ajout d'Espaces qu'Il Fera
'XXXX XXXX XXXX 1234'
format.X
s) de la chaîne(nul l)
dans le début de la zone de texte, et si je tape un caractère au moyen du numéro de la carte, elle saute de mon curseur à la fin.Veuillez vérifier soufflet solution, sa fonctionne très bien pour moi-
Créer de nouveaux swift fichier et collez code ci-dessous, le changement de champ de texte de la classe de VSTextField
Plus utilise peut être trouvé sur le lien ci-dessous
Merci au gars qui a fourni la solution idéale pour la mise en forme du texte dans UITextField.
http://vojtastavik.com/2015/03/29/real-time-formatting-in-uitextfield-swift-basics/
https://github.com/VojtaStavik/VSTextField
De travail idéal pour moi.