I want to concatenate some strings from variables if the variables are not nil. If they are nil, I don't want to include them. The following code works but is clunky and grows proportionately more complex with additional variables. Can anyone recommend a more elegant way to do this?
NSString *city = self.address.city== nil ? #"" : self.address.city;
NSString *state = self.address.state== nil ? #"" : self.address.state;
NSString *zip = self.address.zip== nil ? #"" : self.address.zip;
NSString *bestCity;
if (city.length>0&&state.length>0&&zip.length>0) {
bestCity = [NSString stringWithFormat: #"%# %# %#", city, state,zip];
}
else if (city.length>0&&state.length>0) {
bestName = [NSString stringWithFormat: #"%# %#", city,state];
}
else if (city.length>0&&zip.length>0) {
bestCity = [NSString stringWithFormat: #"%# %#", city,zip];
}
else if (city.length>0&&zip.length>0) {
bestCity = [NSString stringWithFormat: #"%# %#", city,zip];
}
else if (city.length>0) {
bestCity = [NSString stringWithFormat: #"%#", city];
}
else if (state.length>0) {
bestCity = [NSString stringWithFormat: #"%#", state];
}
else if (zip.length>0) {
bestCity = [NSString stringWithFormat: #"%#", zip];
}
else {
bestCity = #"";
}
I usually do something like:
NSMutableArray *bestCityArr = [#[] mutableCopy]; // [[NSMutableArray alloc] init];
if (city.length > 0)
[bestCityArr addObject:city];
if (state.length > 0)
[bestCityArr addObject:state];
if (zip.length > 0)
[bestCityArr addObject:zip];
NSString *bestCity = [bestCityArr componentsJoinedByString:#" "];
NSMutableArray *items = [[NSMutableArray alloc] init];
if (self.address.city)
[items appendObject:self.address.city];
if (self.address.state)
[items appendObject:self.address.state];
if (self.address.zip)
[items appendObject:self.address.zip];
NSString *bestCity = [items componentsJoinedByString:#" "];
This code may help you!
- (NSString *)concatenateString
{
NSMutableString *bestCity = [NSMutableString string];
NSString *city = self.address.city ?: #"";
[bestCity appendString:city];
NSString *state = self.address.state ?: #"";
if (state.length > 0) {
[bestCity appendString:#" "];
}
[bestCity appendString:state]];
NSString *zip = self.address.zip ?: #"";
if (zip.length > 0) {
[bestCity appendString:#" "];
}
[bestCity appendString:zip];
return bestCity.length > 0 ? bestCity : #"";
}
I need to substring to the 2nd comma in an NSString.
Input:
NSString *input = #"title, price, Camry, $19798, active";
Desired Output:
NSString *output = #"title, price";
Thanks!
UPDATE:
I have the following but the problem is it needs to skip the last comma:
NSString *output = [input rangeOfString:#"," options:NSBackwardsSearch];
Try this:
- (NSString *)substringOfString:(NSString *)base untilNthOccurrence:(NSInteger)n ofString:(NSString *)delim
{
NSScanner *scanner = [NSScanner scannerWithString:base];
NSInteger i;
for (i = 0; i < n; i++)
{
[scanner scanUpToString:delim intoString:NULL];
[scanner scanString:delim intoString:NULL];
}
return [base substringToIndex:scanner.scanLocation - delim.length];
}
this code should do what you need:
NSString *input = #"title, price, Camry, $19798, active";
NSArray *array = [input componentsSeparatedByString:#","];
NSArray *subArray = [array subarrayWithRange:NSMakeRange(0, 2)];
NSString *output = [subArray componentsJoinedByString:#","];
NSLog(output);
You could split -> splice -> join that string like this in objc:
NSString *input = #"title, price, Camry, $19798, active";
// split by ", "
NSArray *elements = [input componentsSeparatedByString: #", "];
// grab the subarray
NSArray *subelements = [elements subarrayWithRange: NSMakeRange(0, 2)];
// concat by ", " again
NSString *output = [subelements componentsJoinedByString:#", "];
You can try something like this:
NSArray *items = [list componentsSeparatedByString:#", "];
NSString result = #"";
result = [result stringByAppendingString:[items objectAtIndex:0]];
result = [result stringByAppendingString:#", "];
result = [result stringByAppendingString:[items objectAtIndex:1]];
You have to check you have at least two items if you want avoid an exception.
There's really nothing wrong with simply writing the code to do what you want. Eg:
int commaCount = 0;
int i;
for (i = 0; i < input.count; i++) {
if ([input characterAtIndex:i] == (unichar) ',') {
commaCount++;
if (commaCount == 2) break;
}
}
NSString output = nil;
if (commaCount == 2) {
output = [input substringToIndex:i];
}
You could create an NSString category to handle finding nth occurrences of any string. This is example is for ARC.
//NSString+MyExtension.h
#interface NSString(MyExtension)
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string;
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
options:(NSStringCompareOptions)options;
#end
#implementation NSString(MyExtension)
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
{
return [self substringToNthOccurrence:nth ofString:string options:0];
}
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
options:(NSStringCompareOptions)options
{
NSUInteger location = 0,
strlength = [string length],
mylength = [self length];
NSRange range = NSMakeRange(location, mylength);
while(nth--)
{
location = [self rangeOfString:string
options:options
range:range].location;
if(location == NSNotFound || (location + strlength) > mylength)
{
return [self copy]; //nth occurrence not found
}
if(nth == 0) strlength = 0; //This prevents the last occurence from being included
range = NSMakeRange(location + strlength, mylength - strlength - location);
}
return [self substringToIndex:location];
}
#end
//main.m
#import "NSString+MyExtension.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
NSString *output = [#"title, price, Camry, $19798, active" substringToNthOccurrence:2 ofString:#","];
NSLog(#"%#", output);
}
}
*I'll leave it as an exercise for someone to implement the mutable versions.
I have a text field where the user enters data. It's a phone number field. If the user enters 1234567890, I want it displayed as (123)-(456)-7890 as the user types. How is this possible?
This will help you
Format (xxx) xxx-xxxx
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int length = (int)[self getLength:textField.text];
//NSLog(#"Length = %d ",length);
if(length == 10)
{
if(range.length == 0)
return NO;
}
if(length == 3)
{
NSString *num = [self formatNumber:textField.text];
textField.text = [NSString stringWithFormat:#"(%#) ",num];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"%#",[num substringToIndex:3]];
}
else if(length == 6)
{
NSString *num = [self formatNumber:textField.text];
//NSLog(#"%#",[num substringToIndex:3]);
//NSLog(#"%#",[num substringFromIndex:3]);
textField.text = [NSString stringWithFormat:#"(%#) %#-",[num substringToIndex:3],[num substringFromIndex:3]];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"(%#) %#",[num substringToIndex:3],[num substringFromIndex:3]];
}
return YES;
}
- (NSString *)formatNumber:(NSString *)mobileNumber
{
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
NSLog(#"%#", mobileNumber);
int length = (int)[mobileNumber length];
if(length > 10)
{
mobileNumber = [mobileNumber substringFromIndex: length-10];
NSLog(#"%#", mobileNumber);
}
return mobileNumber;
}
- (int)getLength:(NSString *)mobileNumber
{
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
int length = (int)[mobileNumber length];
return length;
}
This felt more clear and handles removing any unwanted characters much more nicely. Formats correctly for 1 (###) ###‑#### or (###) ###‑####
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *components = [newString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
NSString *decimalString = [components componentsJoinedByString:#""];
NSUInteger length = decimalString.length;
BOOL hasLeadingOne = length > 0 && [decimalString characterAtIndex:0] == '1';
if (length == 0 || (length > 10 && !hasLeadingOne) || (length > 11)) {
textField.text = decimalString;
return NO;
}
NSUInteger index = 0;
NSMutableString *formattedString = [NSMutableString string];
if (hasLeadingOne) {
[formattedString appendString:#"1 "];
index += 1;
}
if (length - index > 3) {
NSString *areaCode = [decimalString substringWithRange:NSMakeRange(index, 3)];
[formattedString appendFormat:#"(%#) ",areaCode];
index += 3;
}
if (length - index > 3) {
NSString *prefix = [decimalString substringWithRange:NSMakeRange(index, 3)];
[formattedString appendFormat:#"%#-",prefix];
index += 3;
}
NSString *remainder = [decimalString substringFromIndex:index];
[formattedString appendString:remainder];
textField.text = formattedString;
return NO;
}
The code bellow is what I typically use. The format is different but you get the picture. This will handle input such as '123df#$#$gdfg45-+678dfg901' and output '1 (234) 567-8901'
#import "NSString+phoneNumber.h"
#implementation NSString (phoneNumber)
-(NSString*) phoneNumber{
static NSCharacterSet* set = nil;
if (set == nil){
set = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
}
NSString* phoneString = [[self componentsSeparatedByCharactersInSet:set] componentsJoinedByString:#""];
switch (phoneString.length) {
case 7: return [NSString stringWithFormat:#"%#-%#", [phoneString substringToIndex:3], [phoneString substringFromIndex:3]];
case 10: return [NSString stringWithFormat:#"(%#) %#-%#", [phoneString substringToIndex:3], [phoneString substringWithRange:NSMakeRange(3, 3)],[phoneString substringFromIndex:6]];
case 11: return [NSString stringWithFormat:#"%# (%#) %#-%#", [phoneString substringToIndex:1], [phoneString substringWithRange:NSMakeRange(1, 3)], [phoneString substringWithRange:NSMakeRange(4, 3)], [phoneString substringFromIndex:7]];
case 12: return [NSString stringWithFormat:#"+%# (%#) %#-%#", [phoneString substringToIndex:2], [phoneString substringWithRange:NSMakeRange(2, 3)], [phoneString substringWithRange:NSMakeRange(5, 3)], [phoneString substringFromIndex:8]];
default: return nil;
}
}
#end
We wrote a custom NSFormatter subclass for phone numbers here: https://github.com/edgecase/PhoneNumberFormatter
You can use it like any other NSFormatter subclass.
Thanks so much for the first answer but, i think, that method -(int)getLength:(NSString*)mobileNumber is useless. You can try something like below:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
int length = [[self formatNumber:[textField text]] length];
if (length == 10) {
if(range.length == 0) {
return NO;
}
}
if (length == 3) {
NSString *num = [self formatNumber:[textField text]];
textField.text = [NSString stringWithFormat:#"(%#) ",num];
if (range.length > 0) {
[textField setText:[NSString stringWithFormat:#"%#",[num substringToIndex:3]]];
}
}
else if (length == 6) {
NSString *num = [self formatNumber:[textField text]];
[textField setText:[NSString stringWithFormat:#"(%#) %#-",[num substringToIndex:3],[num substringFromIndex:3]]];
if (range.length > 0) {
[textField setText:[NSString stringWithFormat:#"(%#) %#",[num substringToIndex:3],[num substringFromIndex:3]]];
}
}
return YES;
}
- (NSString*)formatNumber:(NSString*)mobileNumber {
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
int length = [mobileNumber length];
if (length > 10) {
mobileNumber = [mobileNumber substringFromIndex: length-10];
}
return mobileNumber;
}
For those of you who require international number formatting: https://code.google.com/p/libphonenumber/
Comes with C++, Java and JavaScript implementations. Should be easy to wrap the C++ implementations in a .mm file and write a small Objective-C wrapper around it.
A valid option is https://github.com/iziz/libPhoneNumber-iOS
All the other answer cover only a small part of the possibilities and combinations, this library actually parse and validate EVERY phone number, and identify:
Nationality
phone number type
National carrier
Relevant for U.S. Phone Numbers:
Adding to #wan's post, I added a conditional statement if the user starts with the country code (1). That way, it will format to be: 1 (XXX) XXX-XXXX instead of (1XX) XXX-XXXX.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
textField = self.phoneNumberTextField;
NSInteger length = [self getLength:textField.text];
//NSLog(#"Length = %d ",length);
if ([textField.text hasPrefix:#"1"]) {
if(length == 11)
{
if(range.length == 0)
return NO;
}
if(length == 4)
{
NSString *num = [self formatNumber:textField.text];
textField.text = [NSString stringWithFormat:#"%# (%#) ",[num substringToIndex:1],[num substringFromIndex:1]];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"%#",[num substringToIndex:4]];
}
else if(length == 7)
{
NSString *num = [self formatNumber:textField.text];
NSRange numRange = NSMakeRange(1, 3);
textField.text = [NSString stringWithFormat:#"%# (%#) %#-",[num substringToIndex:1] ,[num substringWithRange:numRange],[num substringFromIndex:4]];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"(%#) %#",[num substringToIndex:3],[num substringFromIndex:3]];
}
} else {
if(length == 10)
{
if(range.length == 0)
return NO;
}
if(length == 3)
{
NSString *num = [self formatNumber:textField.text];
textField.text = [NSString stringWithFormat:#"(%#) ",num];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"%#",[num substringToIndex:3]];
}
else if(length == 6)
{
NSString *num = [self formatNumber:textField.text];
textField.text = [NSString stringWithFormat:#"(%#) %#-",[num substringToIndex:3],[num substringFromIndex:3]];
if(range.length > 0)
textField.text = [NSString stringWithFormat:#"(%#) %#",[num substringToIndex:3],[num substringFromIndex:3]];
}
}
return YES;
}
-(NSString*)formatNumber:(NSString*)mobileNumber
{
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
NSLog(#"%#", mobileNumber);
NSInteger length = [mobileNumber length];
if(length > 10)
{
mobileNumber = [mobileNumber substringFromIndex: length-10];
NSLog(#"%#", mobileNumber);
}
return mobileNumber;
}
-(NSInteger)getLength:(NSString*)mobileNumber
{
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
NSInteger length = [mobileNumber length];
return length;
}
Maybe you could use this simple method:
+ (NSString*) formatPhoneNumber:(NSString *)phoneNumber codeLength:(int) code segmentLength:(int) segment
{
NSString* result = #"";
int length = [phoneNumber length];
NSString* firstSegment = #"";
NSString* restSegment = #"";
for (int i=0; i<length; i++) {
char c = [phoneNumber characterAtIndex:i];
if(i < code)
firstSegment = [firstSegment stringByAppendingFormat:#"%c", c];
else
{
restSegment = [restSegment stringByAppendingFormat:#"%c", c];
int threshold = (i - code) + 1;
if((threshold % segment == 0) && (threshold > 0) && !(threshold > length))
restSegment = [restSegment stringByAppendingFormat:#"%c", '-'];
}
}
result = [result stringByAppendingFormat:#"%#-%#", firstSegment, restSegment];
return result;
}
Assuming above method is in Contact class, just use the method like this:
NSString* phoneNumber = #"085755023455";
NSString* formattedNumber = [Contact formatPhoneNumber:phoneNumber codeLength:3 segmentLength:4];
That would be resulting something like:
085-7550-2345-5
You can use AKNumericFormatterlibrary for it. It has formatter and convenient UITextField category, it's available as a cocoapod.
C# Xamarin.iOS version of most comprehensive answer on how to do phone formatting in iOS is below
public override void ViewDidLoad()
{
base.ViewDidLoad();
PhoneNumberTextField.ShouldChangeCharacters = ChangeCharacters;
}
private bool ChangeCharacters(UITextField textField, NSRange range, string replacementString)
{
var text = textField.Text;
var newString = text.Substring(0, range.Location) + replacementString + text.Substring(range.Location + range.Length);
var decimalString = Regex.Replace(newString, #"[^\d]", string.Empty);
var length = decimalString.Length;
var hasLeadingOne = length > 0 && decimalString[0] == '1';
if ((length == 0) || (length > 10 && !hasLeadingOne) || (length > 11))
{
textField.Text = decimalString;
return false;
}
var index = 0;
var formattedString = "";
if (hasLeadingOne)
{
formattedString += "1";
index += 1;
}
if (length - index > 3)
{
var areaCode = decimalString.Substring(index, 3);
formattedString += "(" + areaCode + ")";
index += 3;
}
if (length - index > 3)
{
var prefix = decimalString.Substring(index, 3);
formattedString += " " + prefix + "-";
index += 3;
}
var remainder = decimalString.Substring(index);
formattedString += remainder;
textField.Text = formattedString;
return false;
}
Also for format +x (xxx) xxx-xx-xx you can use something like this simple solution:
+ (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *components = [newString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
NSString *decimalString = [components componentsJoinedByString:#""];
if (decimalString.length > 11) {
return NO;
}
NSMutableString *formattedString = [NSMutableString stringWithString:decimalString];
[formattedString insertString:#"+" atIndex:0];
if (formattedString.length > 2)
[formattedString insertString:#" (" atIndex:2];
if (formattedString.length > 7)
[formattedString insertString:#") " atIndex:7];
if (formattedString.length > 12)
[formattedString insertString:#"-" atIndex:12];
if (formattedString.length > 15)
[formattedString insertString:#"-" atIndex:15];
textField.text = formattedString;
return NO;}
SWIFT
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let length = self.getTextLength(textField.text)
if length == 10{
if range.length == 0{
return false
}
}
if length == 3{
var num : String = self.formatNumber(textField.text)
textField.text = num + "-"
if(range.length > 0){
textField.text = (num as NSString).substringToIndex(3)
}
}
else if length == 6{
var num : String = self.formatNumber(textField.text)
let prefix = (num as NSString).substringToIndex(3)
let postfix = (num as NSString).substringFromIndex(3)
textField.text = prefix + "-" + postfix + "-"
if range.length > 0{
textField.text = prefix + postfix
}
}
return true
}
func getTextLength(mobileNo: String) -> NSInteger{
var str : NSString = mobileNo as NSString
str = str.stringByReplacingOccurrencesOfString("(", withString: "")
str = str.stringByReplacingOccurrencesOfString(")", withString: "")
str = str.stringByReplacingOccurrencesOfString(" ", withString: "")
str = str.stringByReplacingOccurrencesOfString("-", withString: "")
str = str.stringByReplacingOccurrencesOfString("+", withString: "")
return str.length
}
func formatNumber(mobileNo: String) -> String{
var str : NSString = mobileNo as NSString
str = str.stringByReplacingOccurrencesOfString("(", withString: "")
str = str.stringByReplacingOccurrencesOfString(")", withString: "")
str = str.stringByReplacingOccurrencesOfString(" ", withString: "")
str = str.stringByReplacingOccurrencesOfString("-", withString: "")
str = str.stringByReplacingOccurrencesOfString("+", withString: "")
if str.length > 10{
str = str.substringFromIndex(str.length - 10)
}
return str as String
}
Swift Formatted Phone Number
Improves oppon #datinc's answer,
input such as 1123df#$#$gdfg45-+678dfg901 will be output as +11(234)567-8901
func formattedPhone(phone: String) -> String? {
let notPhoneNumbers = NSCharacterSet.decimalDigitCharacterSet().invertedSet
let str = phone.componentsSeparatedByCharactersInSet(notPhoneNumbers).joinWithSeparator("")
let startIdx = str.startIndex
let endIdx = str.endIndex
let count = str.characters.count
if count == 7 {
return "\(str[startIdx..<startIdx.advancedBy(3)])-\(str[startIdx.advancedBy(3)..<endIdx])"
}else if count == 10{
return "(\(str[startIdx..<startIdx.advancedBy(3)]))\(str[startIdx.advancedBy(3)..<startIdx.advancedBy(6)])-\(str[startIdx.advancedBy(6)..<endIdx])"
}
else if count > 10{
let extra = str.characters.count - 10
return "+\(str[startIdx..<startIdx.advancedBy(extra)])(\(str[endIdx.advancedBy(-10)..<endIdx.advancedBy(-7)]))\(str[endIdx.advancedBy(-7)..<endIdx.advancedBy(-4)])-\(str[endIdx.advancedBy(-4)..<endIdx])"
}
return nil
}
This will help you
Format (xxx) xxx-xxxx For SWIFT 3.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let length = Int(getLength(mobileNumber: textField.text!))
if length == 15 {
if range.length == 0 {
return false
}
}
if length == 3 {
let num = self.formatNumber(mobileNumber: textField.text!)
textField.text = NSString(format:"(%#)",num) as String
if range.length > 0{
let index: String.Index = num.index(num.startIndex, offsetBy: 3)
textField.text = NSString(format:"%#",num.substring(to: index)) as String
}
}else if length == 6 {
let num = self.formatNumber(mobileNumber: textField.text!)
let index: String.Index = num.index(num.startIndex, offsetBy: 3)
textField.text = NSString(format:"(%#) %#-",num.substring(to: index), num.substring(from: index)) as String
if range.length > 0{
textField.text = NSString(format:"(%#) %#",num.substring(to: index), num.substring(from: index)) as String
}
}
return true
}
func formatNumber(mobileNumber: String) -> String {
var number = mobileNumber
number = number.replacingOccurrences(of: "(", with: "")
number = number.replacingOccurrences(of: ")", with: "")
number = number.replacingOccurrences(of: " ", with: "")
number = number.replacingOccurrences(of: "-", with: "")
number = number.replacingOccurrences(of: "+", with: "")
let length = Int(number.characters.count)
if length > 15 {
let index = number.index(number.startIndex, offsetBy: 15)
number = number.substring(to: index)
}
return number
}
func getLength(mobileNumber: String) -> Int {
var number = mobileNumber
number = number.replacingOccurrences(of: "(", with: "")
number = number.replacingOccurrences(of: ")", with: "")
number = number.replacingOccurrences(of: " ", with: "")
number = number.replacingOccurrences(of: "-", with: "")
number = number.replacingOccurrences(of: "+", with: "")
let length = Int(number.characters.count)
return length
}
NSString *str=#"[+]+91[0-9]{10}";
NSPredicate *no=[NSPredicate predicateWithFormat:#"SELF MATCHES %#",str];
if([no evaluateWithObject:txtMobileno.text]==NO
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Warning" message:#"Please Enter correct contact no." delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
So this method will format for (xxx) xxx - xxxx ....
it is a modification of the current top answer and handles backspaces
- (IBAction)autoFormat:(UITextField *)sender {
NSString *mobileNumber = [NSString stringWithFormat:#"%#",sender.text];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
int length = [mobileNumber length];
if(length > 0 && [sender.text length] > self.oldLength){
if(length >= 7 && length <= 10){
sender.text = [NSString stringWithFormat:#"(%#) %# - %#",[mobileNumber substringToIndex:3], [mobileNumber substringWithRange:NSMakeRange(3,3)],[mobileNumber substringWithRange:NSMakeRange(6,[mobileNumber length]-6)]];
} else if(length >= 4 && length <= 6) {
sender.text = [NSString stringWithFormat:#"(%#) %#",[mobileNumber substringToIndex:3], [mobileNumber substringWithRange:NSMakeRange(3,[mobileNumber length]-3)]];
}
if(length >= 11 && length % 4 == 3){
NSString *lastChar = [sender.text substringFromIndex:[sender.text length] - 1];
sender.text = [NSString stringWithFormat:#"%# %#",[sender.text substringToIndex:[sender.text length] - 1],lastChar];
}
self.oldLength = [sender.text length];
} else if([sender.text length] < self.oldLength) {
NSLog(#"deleted - ");
self.oldLength = 0;
sender.text = #"";
for (int i = 0; i < [mobileNumber length]; i = i + 1) {
sender.text = [NSString stringWithFormat:#"%#%#",sender.text,[mobileNumber substringWithRange:NSMakeRange(i, 1)]];
[self autoFormat:sender];
}
}}
hope it helps
REFormattedNumberField is probably the best. Just supply a format you wish.
+(NSString *) phoneNumberFormatterTextField:(NSString *)number forRange:(NSRange)range
{
int length = (int)[[self getPhoneNumber:number] length];
if(length == 3)
{
NSString *num = [MPosBaseScreenController getPhoneNumber:number];
number = [num stringByReplacingOccurrencesOfString:#"(\\d{3})"
withString:#"($1) "
options:NSRegularExpressionSearch
range:NSMakeRange(0, num.length)];
}
else if(length == 6 || length > 6 )
{
NSString *num = [MPosBaseScreenController getPhoneNumber:number];
number = [num stringByReplacingOccurrencesOfString:#"(\\d{3})(\\d{3})"
withString:#"($1) $2 - "
options:NSRegularExpressionSearch
range:NSMakeRange(0, num.length)];
}
return number;
}
Here's a simple category which will mimic the format of the input
#interface NSString (formatDecimalsAs)
- (NSString *)formatDecimalsAs:(NSString *)formattedDecimals;
#end
#implementation NSString (formatDecimalsAs)
- (NSString *)formatDecimalsAs:(NSString *)formattedDecimals
{
// insert non-digit characters from source string
NSMutableString *formattedNumber = [self mutableCopy];
for (int i = 0; i < formattedDecimals.length; i++)
{
if (i > formattedNumber.length)
{
break;
}
unichar character = [formattedDecimals characterAtIndex:i];
if ([[NSCharacterSet decimalDigitCharacterSet].invertedSet characterIsMember:character])
{
[formattedNumber insertString:[NSString stringWithFormat:#"%c", character] atIndex:(NSUInteger) i];
}
}
return formattedNumber;
}
#end
example use
[#"87654321" formatDecimalsAs:#"1111 1111"] // returns #"8765 4321"
Removes all non-digit characters
If 7 digits remain, 123-4567
for 10 digits, (123) 456-7890
Otherwise, groups of three. To adjust the size of the groups, change the value assigned to substrsize
-(NSString*)formatPhone:(NSString*)phone {
NSString *formattedNumber = [[phone componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""];
int substrSize = 3;
NSMutableArray *t = [[NSMutableArray alloc] initWithCapacity:formattedNumber.length / substrSize + 1];
switch (formattedNumber.length) {
case 7:
formattedNumber = [NSString stringWithFormat:#"%#-%#",
[formattedNumber substringToIndex:3],
[formattedNumber substringFromIndex:3]];
break;
case 10:
formattedNumber = [NSString stringWithFormat:#"(%#) %#-%#",
[formattedNumber substringToIndex:3],
[formattedNumber substringWithRange:NSMakeRange(3, 3)],
[formattedNumber substringFromIndex:6]];
break;
default:
for (int i = 0; i < formattedNumber.length / substrSize; i++) {
[t addObject:[formattedNumber substringWithRange:NSMakeRange(i * substrSize, substrSize)]];
}
if (formattedNumber.length % substrSize) {
[t addObject:[formattedNumber substringFromIndex:(substrSize * t.count)]];
}
formattedNumber = [t componentsJoinedByString:#" "];
break;
}
return formattedNumber;
}
In SWIFT 3
func formattedPhone(phone: String) -> String? {
let notPhoneNumbers = CharacterSet.decimalDigits.inverted
let str = phone.components(separatedBy: notPhoneNumbers).joined(separator: "")
let startIdx = str.startIndex
let endIdx = str.endIndex
let count = str.characters.count
if count == 7 {
return "\(str[startIdx..<startIdx.advance(3, for: str)])-\(str[startIdx.advance(3, for: str)..<endIdx])"
}else if count == 10{
return "+1 (\(str[startIdx..<startIdx.advance(3, for: str)])) \(str[startIdx.advance(3, for: str)..<startIdx.advance(6, for: str)])-\(str[startIdx.advance(6, for: str)..<endIdx])"
}
else if count > 10{
let extra = str.characters.count - 10
return "+\(str[startIdx..<startIdx.advance(extra, for: str)]) (\(str[endIdx.advance(-10, for: str)..<endIdx.advance(-7, for: str)])) \(str[endIdx.advance(-7, for: str)..<endIdx.advance(-4, for: str)])-\(str[endIdx.advance(-4, for: str)..<endIdx])"
}
return nil
}
Swift 3 string.index.advancedBy(3) alternate:
extension String.Index{
func advance(_ offset:Int, `for` string:String)->String.Index{
return string.index(self, offsetBy: offset)
}
}
First, add UITextFieldDelegate to your .h file and Delegate your UITextField in the nib file.
Second, add this code to your .m file :
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *filter = #"(###)-(###)-####";
if(!filter) return YES;
NSString *changedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if(range.length == 1 &&
string.length < range.length &&
[[textField.text substringWithRange:range] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:#"0123456789"]].location == NSNotFound)
{
NSInteger location = changedString.length-1;
if(location > 0)
{
for(; location > 0; location--)
{
if(isdigit([changedString characterAtIndex:location]))
{
break;
}
}
changedString = [changedString substringToIndex:location];
}
}
textField.text = [self filteredPhoneStringFromStringWithFilter:changedString :filter];
return NO;
}
-(NSString*) filteredPhoneStringFromStringWithFilter:(NSString*)number : (NSString*)filter{
NSUInteger onOriginal = 0, onFilter = 0, onOutput = 0;
char outputString[([filter length])];
BOOL done = NO;
while(onFilter < [filter length] && !done)
{
char filterChar = [filter characterAtIndex:onFilter];
char originalChar = onOriginal >= number.length ? '\0' : [number characterAtIndex:onOriginal];
switch (filterChar) {
case '#':
if(originalChar=='\0')
{
// We have no more input numbers for the filter. We're done.
done = YES;
break;
}
if(isdigit(originalChar))
{
outputString[onOutput] = originalChar;
onOriginal++;
onFilter++;
onOutput++;
}
else
{
onOriginal++;
}
break;
default:
// Any other character will automatically be inserted for the user as they type (spaces, - etc..) or deleted as they delete if there are more numbers to come.
outputString[onOutput] = filterChar;
onOutput++;
onFilter++;
if(originalChar == filterChar)
onOriginal++;
break;
}
}
outputString[onOutput] = '\0'; // Cap the output string
return [NSString stringWithUTF8String:outputString];
}