How to format UITextField with NSNumberFormatter? - objective-c

Hope this helps others, since I haven't seen any similar post on the web that shows how to format a text field using NSNumberFormatter but at the same time keep the UITextField cursor position to where it should naturally be. Those, because after formatting, the NSString from inside the UITextField and setting it back to the field you end up with the cursor placed an the end of the field.
Also it will be nice to convert it to Swift for those that needs it.

And here is my answer to the issue, I am using a UIKeyboardTypeNumberPad, but also it will work fine with a UIKeyboardTypeDecimalPad, if other keyboard types are used, feel free to add a regex before using the next code:
- (int)getCharOccurencies:(NSString *)character inString:(NSString *)string{
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[string length]];
for (int i=0; i < [string length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [string characterAtIndex:i]];
[characters addObject:ichar];
}
int count = 0;
for (NSString *ichar in characters) {
if ([ichar isEqualToString:character]) {
count++;
}
}
return count;
}
- (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]];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString *charUsedToFormat = #",";
NSMutableString *textString = [NSMutableString stringWithString:[textField text]];
[textField setTintColor:[UIColor darkGrayColor]];
if ([string isEqualToString:charUsedToFormat]) {
return NO;
}
if (range.location == 0 && [string isEqualToString:#"0"]) {
return NO;
}
if ([[textString stringByReplacingCharactersInRange:range withString:string] length] == 0) {
textField.text = #"";
[self selectTextForInput:textField atRange:NSMakeRange(0, 0)];
return NO;
}
NSString *replacebleString = [textString substringWithRange:range];
if (string.length == 0 && [replacebleString isEqualToString:charUsedToFormat]) {
NSRange newRange = NSMakeRange( range.location - 1, range.length);
range = newRange;
textString = [NSMutableString stringWithString:[textString stringByReplacingCharactersInRange:newRange withString:string]];
}else{
textString = [NSMutableString stringWithString:[textString stringByReplacingCharactersInRange:range withString:string]];
}
int commmaCountBefore = [self getCharOccurencies:charUsedToFormat inString:textString];
textString = [NSMutableString stringWithString:[textString stringByReplacingOccurrencesOfString:charUsedToFormat withString:#""]];
NSNumber *firstNumber = [NSNumber numberWithDouble:[textString doubleValue]];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
//just in case
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setGroupingSeparator:charUsedToFormat];
[formatter setDecimalSeparator:#""];
[formatter setMaximumFractionDigits:0];
textString = [NSMutableString stringWithString:[formatter stringForObjectValue:firstNumber]];
textField.text = textString;
int commmaCountAfter = [self getCharOccurencies:charUsedToFormat inString:textString];
int commaDif = commmaCountAfter - commmaCountBefore;
int cursorPossition = (int)range.location + (int)string.length + commaDif;
//set cursor position
NSLog(#"cursorPossition: %d", cursorPossition);
[self selectTextForInput:textField atRange:NSMakeRange(cursorPossition, 0)];
return NO;
}

Related

Multiple colors in NSTextField

I need to change the color for words that are repeating in each line in NSTextField.
I'm using dictionary to separate each line and the dictionary has and array which separates words as data, then i'm checking if the words are repeated and i want to change color or highlight the words that are repeating.. not sure how to do it.
The program is to get word frequency and show type-token, mean frequency and words that are repeating (text colour/highlighted)
any help would be great. right now i'm assigning text to text field from the .txt file imported. got the repeating words and everything.. just need to show which.
current code:
-(NSMutableDictionary*) computeWords:(NSMutableDictionary *)linesDic{
int count = (int)[linesDic count];
int numberOfwords = 0;
int numberOfDiffWords = 0;
NSMutableDictionary* wordComputation = [[NSMutableDictionary alloc]init];
NSMutableDictionary* duplicates = [[NSMutableDictionary alloc]init];
for (int x = 1; x<=count; x++) {
NSMutableArray* duplicateWords = [[NSMutableArray alloc]init];
NSMutableArray* counter = [[NSMutableArray alloc]init];
NSString* key = [NSString stringWithFormat:#"%d", x];
NSArray* data = [linesDic objectForKey:key];
numberOfwords = (int)[data count];
numberOfDiffWords = numberOfwords;
for (int j = 0; j<numberOfwords; j++) {
for (int k = j+1; k<numberOfwords; k++) {
if([[data objectAtIndex:k]isEqualToString:[data objectAtIndex:j]])
{
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}else{
NSString* a = [data objectAtIndex:k];
NSString* b = [data objectAtIndex:j];
if(a.length<b.length){
if((b.length - a.length)<=4){
if([[b substringToIndex:a.length]isEqualToString:a])
{
// NSLog(#"KEY: %# comapare b:%d:%# and a:%d:%#", key,(int)b.length, b, (int)a.length, a );
// NSLog(#"Key: %#, %#", key, [b substringFromIndex:(a.length-1)]);
if([[b substringFromIndex:(a.length)]isEqualToString:#"s"] || [[b substringFromIndex:(a.length)]isEqualToString:#"es"]){
if (([a isEqualToString:#"a"] && [b isEqualToString:#"as"])) {
// NSLog(#"break at key: %#, words %#:%#",key, a, b);
break;
}
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
[duplicateWords addObject:[data objectAtIndex:j]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}
}
}
}else{
if((a.length - b.length)<=4){
if([[a substringToIndex:b.length]isEqualToString:b])
{
// NSLog(#"KEY: %# compare a:%d: %# and b:%d: %#", key,(int)a.length, a, (int)b.length, b );
// NSLog(#"Key: %#, %#", key, [a substringFromIndex:(b.length-1)]);
if([[a substringFromIndex:(b.length)]isEqualToString:#"s"] || [[a substringFromIndex:(b.length)]isEqualToString:#"es"]){
if (([a isEqualToString:#"as"] && [b isEqualToString:#"a"])) {
// NSLog(#"break at key: %#, words %#:%#",key, a, b);
break;
}
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
[duplicateWords addObject:[data objectAtIndex:j]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}
}
}
}
}
}
}
NSNumber* nw = [NSNumber numberWithInt:numberOfwords];
NSNumber* ndw = [NSNumber numberWithInt:numberOfDiffWords];
[counter addObject:nw];
[counter addObject:ndw];
NSLog(#"Key: %#, Data: %#", key, duplicateWords);
[duplicates setObject:duplicateWords forKey:key];
[wordComputation setObject:counter forKey:key];
}
_duplicates = duplicates;
NSLog(#"%#", _duplicates);
_wordComputation = wordComputation;
return wordComputation;
}
-(void)showTable:(NSMutableDictionary*)wordComputation{
int count = (int)[wordComputation count];
int numberOfwords = 0;
int numberOfDiffWords = 0;
// NSLog(#"\t \t Diff Words Words Type Token \t Mean");
for (int x = 1; x<=count; x++) {
NSString* key = [NSString stringWithFormat:#"%d", x];
NSArray* data = [wordComputation objectForKey:key];
numberOfwords = [[data objectAtIndex:0]intValue];
numberOfDiffWords = [[data objectAtIndex:1]intValue];
//print log
// NSLog(#"Line: %# \t %# \t %# \t %# \t\t %#", key, numberOfDiffWords<10?[NSString stringWithFormat:#"0%d", numberOfDiffWords]:[NSString stringWithFormat:#"%d", numberOfDiffWords], numberOfwords<10?[NSString stringWithFormat:#"0%d", numberOfwords]:[NSString stringWithFormat:#"%d", numberOfwords],[NSString stringWithFormat:#"%d/%d", numberOfDiffWords, numberOfwords], [NSString stringWithFormat:#"%d/%d", numberOfwords, numberOfDiffWords]);
}
[_frequencyTable reloadData];
}
tried this just to change color for string first but then it shows
{
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}
on the 5th position in string
- (IBAction)ViewDuplicatesPressed:(id)sender {
[_duplicatesTextField setHidden:NO];
NSLog(#"%#", _duplicates);
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:#"%#", [_contentTextField stringValue]] /*attributes:#{NSForegroundColorAttributeName : [NSColor redColor]}*/];
[attributedString addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(0,5)];
[_duplicatesTextField setStringValue:[NSString stringWithFormat:#"%#", attributedString]];
}
Also Tried
int lineCount = (int)[_linesDic count];
NSString* key;
NSMutableDictionary* dupliDic = [[NSMutableDictionary alloc]init];
for (int i = 0; i<lineCount; i++) {
NSArray *duplicateWords;
key = [NSString stringWithFormat:#"%d", i];
duplicateWords = [_duplicates objectForKey:key];
NSMutableAttributedString *attributedString;
NSString* stringForKey = [NSString stringWithFormat:#"%#", [_linesDic objectForKey:key]];
for (int j =0 ; i < (int)[duplicateWords count]; j++) {
NSString* word = [duplicateWords objectAtIndex:j];
NSRange range = [stringForKey rangeOfString:word];
attributedString = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:#"%#", [_linesDic objectForKey:key]] /*attributes:#{NSForegroundColorAttributeName : [NSColor redColor]}*/];
[attributedString addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:range];
}
[dupliDic setObject:attributedString forKey:key];
}
[_duplicatesTextField setHidden:NO];
NSLog(#"%#", dupliDic);
[_duplicatesTextField setStringValue:[NSString stringWithFormat:#"%#", dupliDic]];

How to print the reverse of NSString in objective c without using componentsSeparatedByString method?

I want to make a method which gives reverse of string.suppose I pass a NSString "Welcome to Objective C" in method and that method return a reverse of string like "C Objective to Welcome" not "C evitcejbO ot emocleW" without the use of componentsSeparatedByString method.
Is it possible to do with Objective c..?
Please help.
You can enumerate strings by words.
NSString *string = #"Welcome to Objective-C!";
NSMutableArray *words = [NSMutableArray array];
[string enumerateLinguisticTagsInRange:NSMakeRange(0, [string length])
scheme:NSLinguisticTagSchemeTokenType
options:0
orthography:nil
usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
[array addObject:[string substringWithRange:tokenRange]];
}];
NSMutableString *reverseString = [[NSMutableString alloc] init];
for (NSString *word in [words reverseObjectEnumerator]){
[reverse appendString:word];
}
NSLog(#"%#", reverseString);
This will print...
"!C-Objective to Welcome"
You can change the options to omit whitespaces and stuff...
I used below method for reversing string in iOS
- (NSString *)reverseString:(NSString *)stringToReverse
{
NSMutableString *reversedString = [NSMutableString stringWithCapacity:[stringToReverse length]];
[stringToReverse enumerateSubstringsInRange:NSMakeRange(0, [stringToReverse length])
options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reversedString appendString:substring];
}];
return reversedString;
}
Sorry I misread your question earlier. I did it using a series of loops, my answer is messier than Fogmeister but I wanted to give it a shot to see if I could do it.
NSString *str = #"This is a test";
NSMutableArray *array = [[NSMutableArray alloc] init];
for(int i = 0; i < [str length]; i++)
{
char sTest = [str characterAtIndex:i];
if(sTest == ' ')
{
[array addObject:[NSNumber numberWithInt:i]];
}
}
NSInteger iNext = [[array objectAtIndex:[array count]-1] integerValue];
iNext+=1;
if(iNext < [str length])
{
[array addObject:[NSNumber numberWithInt:iNext]];
}
NSMutableArray *wordArray = [[NSMutableArray alloc] init];
for(int i = 0; i < [array count]; i++)
{
if (i == 0)
{
int num = [[array objectAtIndex:i] integerValue];
NSString *s = [[str substringFromIndex:0] substringToIndex:num];
[wordArray addObject:s];
}
else if(i == [array count]-1)
{
int prev = [[array objectAtIndex:i-1] integerValue]+1;
int num = [str length];
NSString *s = [[str substringToIndex:num] substringFromIndex:prev];
[wordArray addObject:s];
}
else
{
int prev = [[array objectAtIndex:i-1] integerValue]+1;
int num = [[array objectAtIndex:i] integerValue];
NSString *s = [[str substringToIndex:num] substringFromIndex:prev];
[wordArray addObject:s];
}
}
NSMutableArray *reverseArray = [[NSMutableArray alloc]init];
for(int i = [wordArray count]-1; i >= 0; i--)
{
[reverseArray addObject:[wordArray objectAtIndex:i]];
}
NSLog(#"%#", reverseArray);
Here i have done with replacing character with minimal number of looping. log(n/2).
NSString *string=#"Happy World";
NSInteger lenth=[string length];
NSInteger halfLength=[string length]/2;
for(int i=0;i<halfLength;i++)
{
NSString *leftString=[NSString stringWithFormat:#"%c",[string characterAtIndex:i]];
NSString *rightString=[NSString stringWithFormat:#"%c",[string characterAtIndex:(lenth-i-1)]];
string= [string stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:rightString];
string=[string stringByReplacingCharactersInRange:NSMakeRange((lenth-i-1), 1) withString:leftString];
}
NSLog(#"%#",string);
Try This , It's working perfect as per your expectation ,
Call Function :-
[self reversedString:#"iOS"];
Revers String Function :-
-(void)reversedString :(NSString *)reversStr
{ // reversStr is "iOS"
NSMutableString *reversedString = [NSMutableString string];
NSInteger charIndex = [reversStr length];
while (charIndex > 0) {
charIndex--;
NSRange subStrRange = NSMakeRange(charIndex, 1);
[reversedString appendString:[reversStr substringWithRange:subStrRange]];
}
NSLog(#"%#", reversedString); // outputs "SOi"
}
Hope So this is help for some one .
There is no API to do that, if that's what you are asking.
You can always iterate through the string looking for white spaces (or punctuation, it depends on your needs), identify the words and recompose your "reversed" message manually.

Split NSString with multiple delimiters?

For text bozo__foo!!bar.baz, how to split an NSString containing this into (bozo, foo, bar, baz)?
That is, separe it in components with strings (delimiters) __, !! and ..
You can split the strings using NSCharacterSet. Try this
NSString *test=#"bozo__foo!!bar.baz";
NSString *sep = #"_!.";
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:sep];
NSArray *temp=[test componentsSeparatedByCharactersInSet:set];
NSLog(#"temp=%#",temp);
I'm aware that this question has already been answered but this is a way to separate strings using multiple strings. This is a category to NSString.
- (NSArray<NSString *> *)componentsSeparatedByStrings:(NSArray<NSString *> *)separators
{
NSMutableArray<NSString *> *components = [[NSMutableArray alloc] init];
unichar buffer[self.length + 1];
NSInteger currentOrigin = 0;
NSInteger currentLength = 0;
[self getCharacters:buffer];
for(NSInteger i = 0; i < self.length; i++)
{
unichar currentChar = buffer[i];
currentLength++;
for(NSInteger n = 0; n < separators.count; n++)
{
NSString *currentDivider = [separators objectAtIndex:n];
if(currentDivider.length == 0)
{
return #[self];
}
else if(currentDivider.length > 1)
{
BOOL goodMatch = NO;
for(NSInteger x = 0; x < currentDivider.length; x++)
{
unichar charInDivider = [currentDivider characterAtIndex:x];
if(charInDivider == currentChar)
{
goodMatch = YES;
}
else
{
goodMatch = NO;
break;
}
if(goodMatch == YES && ((x + 1) != currentDivider.length))
{
i++;
currentLength++;
currentChar = buffer[i];
}
}
if(goodMatch == YES)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - currentDivider.length));
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = (i + 1);
currentLength = 0;
[components addObject:newComponent];
NSLog(#"%#", components);
}
}
else // If current divider is only one character long.
{
if([currentDivider characterAtIndex:0] == currentChar)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - 1));
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = (i + 1);
currentLength = 0;
[components addObject:newComponent];
break;
}
}
}
// Handle the end of the string.
if((i + 1) == self.length)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, currentLength);
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = 0;
currentLength = 0;
[components addObject:newComponent];
}
}
return components;
}
Example: "ABCD__EFGHI__JKLMNOP-QRST.UV_WXYZ"
NSLog(#"%#", [test componentsSeparatedByStrings:#[#"__", #"-", #"."]]);
Log Result: "(ABCD, EFGHI, JKLMNOP, QRST, "UV_WXYZ")"
NSString *text = #"bozo__foo!!bar.baz";
NSArray *split1 = [text componentsSeparatedByString:#"__"];
NSArray *split2 = [[split1 lastObject] componentsSeparatedByString:#"!!"];
NSArray *split3 = [[split2 lastObject] componentsSeparatedByString:#"."];
NSLog(#"%#, %#, %#, %#", split1[0], split2[0], split3[0], split3[1]);
More functional solution is to apply -componentsSeparatedByString: recursively, for each component, which was derived during previous separator application:
NSString Category
- (NSMutableArray<NSString *> *)gvr_componentsSeparatedByStrings:(NSArray<NSString *> *)separators {
if (separators.count == 0) {
return [NSMutableArray arrayWithObject:self];
}
NSString *separator = [separators firstObject];
NSArray *reducedSeparators = [separators gvr_arrayByRemovingFirstObject];
NSArray *components = [self componentsSeparatedByString:separator];
NSMutableArray *result = [NSMutableArray new];
for (NSString *component in components) {
NSMutableArray *subResult = [component gvr_componentsSeparatedByStrings:reducedSeparators];
[result addObjectsFromArray:subResult];
}
return result;
}
NSArray Category
- (NSArray *)gvr_arrayByRemovingFirstObject {
NSMutableArray *result = [NSMutableArray new];
for (NSInteger i = 1; i < self.count; i++) {
[result addObject:self[i]];
}
return [result copy];
}
I solved it for my project by looking for the longest separator, replacing the others with this one, then do the separation on the only one left.
Try this:
NSString *test = #"bozo__foo!!bar.baz";
test = [test stringByReplacingOccurrencesOfString:#"!!" withString:#"__"];
test = [test stringByReplacingOccurrencesOfString:#"." withString:#"__"];
NSArray<NSString *> *parts = [test componentsSeparatedByString:#"__"];

If textField is empty, do not filter my array to nothing

This works fine if the textField is containing any text. But if the textField is empty, no objects are added.
How to tell this piece of code that if the textField is empty, all objects should be added to resultObjectsArray?
resultObjectsArray = [NSMutableArray array];
for(NSDictionary *object in allObjectsArray)
{
NSString *nameString = [NSString stringWithFormat:#"%#", [textField text]];
NSString *wineName = [wine objectForKey:#"Name"];
NSRange range = [wineName rangeOfString:nameString options:NSCaseInsensitiveSearch];
if ((range.location != NSNotFound))
[resultObjectsArray addObject:object];
}
resultObjectsArray = [NSMutableArray array];
NSString *nameString = [textField text];
for(NSDictionary *object in allObjectsArray)
{
if ([nameString length] > 0)
{
NSString *wineName = [wine objectForKey:#"Name"];
NSRange range = [wineName rangeOfString:nameString options:NSCaseInsensitiveSearch];
if ((range.location != NSNotFound))
[resultObjectsArray addObject:object];
}
else
{
[resultObjectsArray addObject:object];
}
}
Note that you don't need:
NSString *nameString = [NSString stringWithFormat:#"%#", [textField text]];
as
NSString *nameString = [textField text];
is sufficient. Also it won't change inside the for loop so can be initialised outside of it.
That's how the code ended up looking like using the answer from #trojanfoe. (I've excluded my other search criterias).
-(IBAction)searchButtonPressed:(id)sender{
BOOL textFieldIsEdited = NO;
if ([[textField text] length] > 0)
{
textFieldIsEdited = YES;
}
resultObjectsArray = [NSMutableArray array];
for(NSDictionary *wine in allObjectsArray)
{
BOOL nameMatch = YES;
if (textFieldIsEdited) {
NSString *wineName = [wine objectForKey:#"Name"];
NSString *nameString = [textField text];
NSRange range = [wineName rangeOfString:nameString options:NSCaseInsensitiveSearch];
if (range.location == NSNotFound) {
nameMatch = NO;
}
}
if ((nameMatch != NO))
[resultObjectsArray addObject:wine];
}

NSNumberFormatter not allowing decimal input

If I enter a decimal point '.' into my UITextField, the number formatter called does not recognise the decimal point and continues as if the decimal point has not been entered. I.e If I entered 200.9, the decimal point would not show up in the textfield and the text of the textfield would be 2009.
I want to limit the number of digits after the decimal point to 2 as I believe I am doing below. Please can you tell me what I am doing to cause this?
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
BOOL isDeleting = [textField.text substringWithRange:range].length > string.length;
int index = [textFields indexOfObject:textField];
NSString *input;
if (isDeleting == NO)
input = [textField.text stringByAppendingString:string];
else {
NSMutableString *str = [textField.text mutableCopy];
[str deleteCharactersInRange:range];
input = [[str copy] autorelease];
[str release];
}
if ([input isEqualToString:#"£"] || ([input isEqualToString:#""] && index != 1)) {
[textField setText:#"£"];
}
else {
if (index != 1)
[textField setText:[self numberFormattedString:input]];
else
[textField setText:input];
}
return NO;
}
- (NSString *) numberFormattedString:(NSString *)str {
str = [str stringByReplacingOccurrencesOfString:#"£" withString:#""];
str = [str stringByReplacingOccurrencesOfString:#"," withString:#""];
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en-UK"];
[formatter setLocale:locale];
[locale release];
[formatter setAllowsFloats:YES];
[formatter setMaximumFractionDigits:3];
[formatter setMinimumFractionDigits:0];
[formatter setDecimalSeparator:#"."];
return [formatter stringFromNumber:[NSNumber numberWithFloat:[str floatValue]]];
}
TIA.
Let's say you enter the number 100 and then a decimal point. When numberFormattedString is called with the string £100., it's going to get rid of the £, and str will contain the string 100. which [str floatValue] converts to the float value 100, and finally your number formatter spits it back out as the string £100 without any decimal point. So basically [str floatValue] is killing your decimal point.
One solution is to check for when you get the decimal point as your replacement string in the text field delegate method, and skip calling numberFormattedString in that case. Then when the user enters the next digit, you can carry on calling numberFormattedString, and the conversion should happen correctly. You'll just have to make sure that the user can only enter one decimal point.
EDIT: I just realized that my suggested solution still won't work if you enter a 0 after the decimal point (e.g. 100.0), but I'm sure there is a minor tweak that you can figure out to solve that.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *numSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789."];
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
int charCount = [newString length];
if ([newString rangeOfCharacterFromSet:[numSet invertedSet]].location != NSNotFound
|| [string rangeOfString:#"."].location != NSNotFound
|| charCount > 15) {
return NO;
}
// if (charCount == 4 || charCount == 9 || charCount==13) {
// newString = [newString stringByAppendingString:#"."];
// }
NSLog(#"IN method");
textField.text = newString;
return NO;
}