iOS Automatically Add Hyphen in Text Field

iOS automatically add hyphen in text field

Be aware the previous answer is woefully inadequate. Heaven forbid your user enter an incorrect digit and dare attempt to delete it! In fairness, the poster noted the code may not work perfectly. But then, it wouldn't even compile, so the buyer beware filter should already be high. If you fix the compile error and try the code, you'll see you can easily end up with input that does not match the poster's stated format.

Here's a solution I've used for restricting a text field to a phone number of the format 123-456-7890. Adjusting for other numeric formats is trivial. Note the use of the passed NSRange. And BTW, rejecting non-digit characters is needed even when using a numeric virtual keyboard since users can still enter non-digits via a hardware keyboard.

One other note. I add the hyphen after the entry of the 4th and 7th digits to make the deleting of digits a bit easier. If you add after the 3rd and 6th digits, you will have to handle the case of deleting the dangling hyphen. The code below avoids that use case.

// Restrict entry to format 123-456-7890
- (BOOL) textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {

// All digits entered
if (range.location == 12) {
return NO;
}

// Reject appending non-digit characters
if (range.length == 0 &&
![[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[string characterAtIndex:0]]) {
return NO;
}

// Auto-add hyphen before appending 4rd or 7th digit
if (range.length == 0 &&
(range.location == 3 || range.location == 7)) {
textField.text = [NSString stringWithFormat:@"%@-%@", textField.text, string];
return NO;
}

// Delete hyphen when deleting its trailing digit
if (range.length == 1 &&
(range.location == 4 || range.location == 8)) {
range.location--;
range.length = 2;
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@""];
return NO;
}

return YES;
}

Add hyphen automatically in text field but not able to edit the textfield (Phone number masking)

This code will also work when we will do copy-paste text in UITextField.

Warning- This code won't work with your keyboard's delete button. Anyway you need only keyboard's backspace button because Mobile keypad's delete button work like keyboard's backspace button

Note- use tag for your UITextField instead of directly compare textField to your outlet

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//(textField == txtUserName)
// don't compare with ID, use tag
if(textField.tag == 0 )
{
NSString *text = textField.text;
NSUInteger textLength = text.length;
NSString *trimText = [text stringByReplacingOccurrencesOfString:@"-" withString:@""];
NSUInteger trimTextLength = trimText.length;

if (range.length == 0 && [string rangeOfCharacterFromSet: [[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
{
return NO;
}
if( string.length > 0 ) {
NSString *replacedText = text;
if(trimTextLength < 10) {
NSInteger remainingNumbers = (10-trimTextLength);
if(string.length > remainingNumbers) {
string = [string substringToIndex:remainingNumbers];
}
replacedText = [replacedText stringByReplacingCharactersInRange:range withString:string];
}
NSString *trimReplacedText = [replacedText stringByReplacingOccurrencesOfString:@"-" withString:@""];
if( trimReplacedText.length > 3 ) {
trimReplacedText = [trimReplacedText stringByReplacingCharactersInRange:NSMakeRange(3, 0) withString:@"-"];
}
if( trimReplacedText.length > 7 ) {
trimReplacedText = [trimReplacedText stringByReplacingCharactersInRange:NSMakeRange(7, 0) withString:@"-"];
}
textField.text = trimReplacedText;
return NO;
}
bool flag = false;
if (range.length == 1 &&(range.location == 4 || (range.location == 7 && (textLength-trimTextLength)== 1 && [text rangeOfString:@"-"].location == 7) || (range.location == 8 && (textLength-trimTextLength)== 2) ))
{
range.location--;
range.length = 2;
flag = true;
}
else if (range.length >= 1)
{
flag = true;
}

if(flag) {
NSString *replacedText = [textField.text stringByReplacingCharactersInRange:range withString:@""];

NSString *trimReplacedText = [replacedText stringByReplacingOccurrencesOfString:@"-" withString:@""];
if( trimReplacedText.length > 3 ) {
trimReplacedText = [trimReplacedText stringByReplacingCharactersInRange:NSMakeRange(3, 0) withString:@"-"];
}
if( trimReplacedText.length > 7 ) {
trimReplacedText = [trimReplacedText stringByReplacingCharactersInRange:NSMakeRange(7, 0) withString:@"-"];
}
textField.text = trimReplacedText;
return NO;
}
}
return YES;
}

Adding hyphen between textfield character when typing in text filed

This should work if you do not copy paste text to the text field.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text, let textRange = Range(range, in: text) {
let updatedText = text.replacingCharacters(in: textRange, with: string)
if textField.text?.count == 3 && updatedText.count == 4 {
textField.text = textField.text! + "-" + string
return false
}
if textField.text?.count == 5 && updatedText.count == 4 {
let text = textField.text!
textField.text = String(text.prefix(3))
return false
}
}
return true
}

P.S - Your text field keyboard should be number pad.

yourTextField.keyboardType = .numberPad

How to Input Dash After Every 4th Character in Objective-C

This has worked excellently for me:

iOS automatically add hyphen in text field

Check the answer by "dingo sky".

Add Separator - in text field in Swift iOS

// try like this

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool 
{
var strText: String? = textField.text
if strText == nil {
strText = ""
}
strText = strText?.stringByReplacingOccurrencesOfString("-", withString:"")
if strText!.characters.count > 1 && strText!.characters.count % 4 == 0 && string != "" {
textField.text = "\(textField.text!)-\(string)"
return false
}

return true
}

Adding hyphens with CFStringGetHyphenationLocationBeforeIndex

Before creating the attributed string you could add soft hyphenation. Then you could do the drawing.

I wrote a category for adding "soft hyphenation" to any string. These are "-" which is not visible when rendered, but instead merely queues for CoreText or UITextKit to know how to break up words.

NSString *string = @"accessibility tests and frameworks checking";
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
NSString *hyphenatedString = [string softHyphenatedStringWithLocale:locale error:nil];
NSLog(@"%@", hyphenatedString);

Outputs ac-ces-si-bil-i-ty tests and frame-works check-ing


NSString+SoftHyphenation.h

typedef enum {
NSStringSoftHyphenationErrorNotAvailableForLocale
} NSStringSoftHyphenationError;

extern NSString * const NSStringSoftHyphenationErrorDomain;
extern NSString * const NSStringSoftHyphenationToken;

@interface NSString (SoftHyphenation)

- (BOOL)canSoftHyphenateStringWithLocale:(NSLocale *)locale;
- (NSString *)softHyphenatedStringWithLocale:(NSLocale *)locale error:(out NSError **)error;

@end

NSString+SoftHyphenation.m

#import "NSString+SoftHyphenation.h"

NSString * const NSStringSoftHyphenationErrorDomain = @"NSStringSoftHyphenationErrorDomain";
NSString * const NSStringSoftHyphenationToken = @"­"; // NOTE: UTF-8 soft hyphen!

@implementation NSString (SoftHyphenation)

- (BOOL)canSoftHyphenateStringWithLocale:(NSLocale *)locale
{
CFLocaleRef localeRef = (__bridge CFLocaleRef)(locale);
return CFStringIsHyphenationAvailableForLocale(localeRef);
}

- (NSString *)softHyphenatedStringWithLocale:(NSLocale *)locale error:(out NSError **)error
{
if(![self canSoftHyphenateStringWithLocale:locale])
{
if(error != NULL)
{
*error = [self hyphen_createOnlyError];
}
return [self copy];
}
else
{
NSMutableString *string = [self mutableCopy];
unsigned char hyphenationLocations[string.length];
memset(hyphenationLocations, 0, string.length);
CFRange range = CFRangeMake(0, string.length);
CFLocaleRef localeRef = (__bridge CFLocaleRef)(locale);

for(int i = 0; i < string.length; i++)
{
CFIndex location = CFStringGetHyphenationLocationBeforeIndex((CFStringRef)string, i, range, 0, localeRef, NULL);

if(location >= 0 && location < string.length)
{
hyphenationLocations[location] = 1;
}
}

for(int i = string.length - 1; i > 0; i--)
{
if(hyphenationLocations[i])
{

[string insertString:NSStringSoftHyphenationToken atIndex:i];
}
}

if(error != NULL) { *error = nil; }

// Left here in case you want to test with visible results
// return [string stringByReplacingOccurrencesOfString:NSStringSoftHyphenationToken withString:@"-"];
return string;
}
}

- (NSError *)hyphen_createOnlyError
{
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"Hyphenation is not available for given locale",
NSLocalizedFailureReasonErrorKey: @"Hyphenation is not available for given locale",
NSLocalizedRecoverySuggestionErrorKey: @"You could try using a different locale even though it might not be 100% correct"
};
return [NSError errorWithDomain:NSStringSoftHyphenationErrorDomain code:NSStringSoftHyphenationErrorNotAvailableForLocale userInfo:userInfo];
}

@end

Hope this helps :)

How to insert a string automatically while user editing UITEXTFIELD

The following code should do the following:

  1. Limit the number of characters that can be typed/pasted into the text field
  2. Automatically add periods and slashes at the appropriate locations
  3. Prevent issues from the user copy/pasting a string that already has the necessary periods/slashes

That said, there is almost certainly more efficient ways to do this; but if you're not concerned about code length it'll do the trick just fine.

- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *text = textField.text;

// If we're trying to add more than the max amount of characters, don't allow it
if ([text length] == 14 && range.location > 13) {
return NO;
}

// First lets add the whole string we're going for
text = [text stringByReplacingCharactersInRange:range withString:string];

// Now remove spaces, periods, and slashes (since we'll add these automatically in a minute)
text = [text stringByReplacingOccurrencesOfString:@" " withString:@""];
text = [text stringByReplacingOccurrencesOfString:@"." withString:@""];
text = [text stringByReplacingOccurrencesOfString:@"/" withString:@""];

// We need to use an NSMutableString to do insertString calls in a moment
NSMutableString *mutableText = [text mutableCopy];

// Every 4th char will be a '.', but we don't want to check more than the first 8 characters
for (NSUInteger i = 3; i < mutableText.length && i < 8; i += 4) {
[mutableText insertString:@"." atIndex:i];
}
// If the text is more than 11 characters, we also want to insert a '/' at the 11th character index
if (mutableText.length > 11) {
[mutableText insertString:@"/" atIndex:11];
}

// lets set text to our new string
text = mutableText;

// Now, lets check if we need to cut off extra characters (like if the person pasted a too-long string)
if (text.length > 14) {
text = [text stringByReplacingCharactersInRange:NSMakeRange(14, mutableText.length-14) withString:@""];
}

// Finally, set the textfield to our newly modified string!
textField.text = text;

return NO;
}


Related Topics



Leave a reply



Submit