Carl-
Carl-

Reputation: 241

How do I format a String to credit card format?

What is the easiest way to format a string like "1234567890123456789" to "1234 5678 9012 3456 789" in iOS?

Upvotes: 1

Views: 2692

Answers (5)

Kepler
Kepler

Reputation: 705

Try this:

-(NSString *) correctString:(NSString *) anyStr {
    NSMutableString *str = [NSMutableString stringWithString:anyStr];
    int indx=4;
    while (indx<str.length) {
        [str insertString:@" " atIndex:indx];
        indx +=5;
    }
    anyStr=str;
    return anyStr;
}

Upvotes: 3

Hardik Thakkar
Hardik Thakkar

Reputation: 15991

Here is a Swift extension:

extension String {
    var pairs: [String] {
        var result: [String] = []
        let chars = Array(characters)
        for index in 0.stride(to: chars.count, by: 4) {
            result.append(String(chars[index..<min(index+4, chars.count)]))
        }
        return result
    }
}

To use:

let string : String = "1234567890123456789"
let finalString = string.pairs.joinWithSeparator(" ") //1234 5678 9012 3456 789
print(finalString)

For Swift 3:

extension String {
    var pairs: [String] {
        var result: [String] = []
        let chars = Array(characters)
        for index in stride(from: 0, to: chars.count, by: 4){
            result.append(String(chars[index..<min(index+4, chars.count)]))
        }
        return result
    }
}

Upvotes: 0

Dren
Dren

Reputation: 2107

I propose to use NSString category. In not ARC just add autorelease after self copy. My variant will not add spaces after last digits quarter if it is not nescessary. Applicable to use in UITextField.

- (NSString *)creditCardNumberFormatedString {
    NSString *string = [self copy];
    NSUInteger length = string.length;
    if (length >= 17) {
        string = [string substringToIndex:16];
        length = 16;
    }

    BOOL isSpaceRequired = YES;
    if (length == 4) {
        isSpaceRequired = NO;

    }

    NSString *newString = [NSString new];
    while (string.length > 0) {
        NSString *subString = [string substringToIndex:MIN(string.length, 4)];
        newString = [newString stringByAppendingString:subString];
        if (subString.length == 4 && isSpaceRequired) {
            newString = [newString stringByAppendingString:@" "];
        }

        string = [string substringFromIndex:MIN(string.length, 4)];
        if (string.length <= 4) {
            isSpaceRequired = NO;
        }
    }

    return newString;
}

Upvotes: 0

Rob
Rob

Reputation: 438122

For that particular format, you could do something like the following, which extracts the individual substrings:

NSString *string = @"1234567890123456789";
NSMutableArray *array = [NSMutableArray array];
for (NSInteger i = 0; i < [string length]; i += 4)
    [array addObject:[string substringWithRange:NSMakeRange(i, MIN(4, [string length] - i))]];
NSString *result = [array componentsJoinedByString:@" "];

The thing is, not all credit cards conform to the xxxx xxxx xxxx xxxx format. E.g., Amex uses a xxxx xxxxxx xxxxx format. You really should look at the first digits of the card, determine the type of card, and format it accordingly.


You asked if you could do it with a regular expression. Consider this regex:

NSString *result = [string stringByReplacingOccurrencesOfString:@"^[\\s-]*([0-9]{4})[\\s-]*([0-9]{4})[\\s-]*([0-9]{4})[\\s-]*([0-9]{4})[\\s-]*([0-9]{3})[\\s-]*$"
                                                     withString:@"$1 $2 $3 $4 $5"
                                                        options:NSRegularExpressionSearch
                                                          range:NSMakeRange(0, [string length])];

That will convert any of the following:

@"1234567890123456789"
@"1234-5678-9012-3456-789"
@"  1234567890123456789  "

into:

@"1234 5678 9012 3456 789"

While you could use regular expression, it's sufficiently opaque that I wouldn't particularly advise it. But it can be done.

Upvotes: 3

Rukkora
Rukkora

Reputation: 186

I wrote code.

NSMutableString *string = @"1234567890123456789"; 

NSInteger *ip = 4;

for (NSInteger i = 0; i*4 < [string length] ; i++)
{
    [string insertString:@" " atIndex:ip];
    ip = ip+5;
}

Upvotes: 0

Related Questions