web-dev-qa-db-fra.com

Contrôler la position du curseur dans UITextField

J'ai un UITextField que je force à formater en modifiant le texte à l'intérieur du gestionnaire de notification de modification. Cela fonctionne très bien (une fois que j'ai résolu les problèmes de réentrance) mais me laisse avec un problème persistant . Si l'utilisateur déplace le curseur ailleurs que la fin de la chaîne, ma modification de formatage le déplace à la fin de la chaîne. Cela signifie que les utilisateurs ne peuvent pas insérer plus d'un caractère à la fois au milieu du champ de texte. Y a-t-il un moyen de se souvenir puis de réinitialiser la position du curseur dans UITextField?

47
Jeremy

Contrôler la position du curseur dans un UITextField est compliqué car de nombreuses abstractions sont impliquées dans les zones de saisie et le calcul des positions. Cependant, c'est certainement possible. Vous pouvez utiliser la fonction membre setSelectedTextRange:

[input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];

Voici une fonction qui prend une plage et sélectionne les textes de cette plage. Si vous souhaitez simplement placer le curseur à un certain index, utilisez simplement une plage de longueur 0:

+ (void)selectTextForInput:(UITextField *)input atRange:(NSRange)range {
    UITextPosition *start = [input positionFromPosition:[input beginningOfDocument] 
                                                 offset:range.location];
    UITextPosition *end = [input positionFromPosition:start
                                               offset:range.length];
    [input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];
}

Par exemple, pour placer le curseur sur idx dans la propriété UITextField input:

    [Helpers selectTextForInput:input 
                        atRange:NSMakeRange(idx, 0)];
66
Chris R

Utile pour se positionner à l'index (Swift 3)

private func setCursorPosition(input: UITextField, position: Int) {
    let position = input.position(from: input.beginningOfDocument, offset: position)!
    input.selectedTextRange = input.textRange(from: position, to: position)
}
4
George Muntean

J'ai enfin trouvé une solution à ce problème! Vous pouvez insérer le texte dont vous avez besoin dans la table de montage du système, puis le coller à la position actuelle du curseur: 

[myTextField paste:self]  

J'ai trouvé la solution sur le blog de cette personne:
 http://dev.ragfield.com/2009/09/insert-text-at-current-cursor-location.html

La fonctionnalité de collage est spécifique à OS V3.0, mais je l’ai testée et elle fonctionne parfaitement pour moi avec un clavier personnalisé. 

Si vous optez pour cette solution, vous devriez probablement sauvegarder le contenu du presse-papiers existant de l'utilisateur et le restaurer immédiatement après.

3
Dan J

Voici la version Swift de @Chris R. - mise à jour pour Swift3

private func selectTextForInput(input: UITextField, range: NSRange) {
    let start: UITextPosition = input.position(from: input.beginningOfDocument, offset: range.location)!
    let end: UITextPosition = input.position(from: start, offset: range.length)!
    input.selectedTextRange = input.textRange(from: start, to: end)
}
2
gabuchan

N'hésitez pas à utiliser cette catégorie UITextField pour obtenir et définir la position du curseur:

@interface UITextField (CursorPosition)

@property (nonatomic) NSInteger cursorPosition;

@end

-

@implementation UITextField (CursorPosition)

- (NSInteger)cursorPosition
{
    UITextRange *selectedRange = self.selectedTextRange;
    UITextPosition *textPosition = selectedRange.start;
    return [self offsetFromPosition:self.beginningOfDocument toPosition:textPosition];
}

- (void)setCursorPosition:(NSInteger)position
{
    UITextPosition *textPosition = [self positionFromPosition:self.beginningOfDocument offset:position];
    [self setSelectedTextRange:[self textRangeFromPosition:textPosition toPosition:textPosition]];
}

@end
1
Pavel Alexeev

Je ne pense pas qu'il y ait un moyen de placer le curseur à un endroit particulier de votre UITextField (à moins que vous ne deveniez très difficile et simulait un événement tactile). Au lieu de cela, je m'occuperais du formatage lorsque l'utilisateur a fini édite son texte (en textFieldShouldEndEditing:) et si son entrée est incorrecte, n'autorisez pas le champ de texte à être édité.

0
pix0r