I have always implemented this with a custom
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
routine. You monitor the characters as they come in and only accept the numerics.
I used a UITextField, and implemented the UITextFieldDelegate methods outlined below:
// This method enforces the textField to give up first responder and return
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
// This method copies the current UITextField' text into a string used for editing
// comparing, and for if a cancelation occurs we can replace with the original text
-(void)textFieldDidBeginEditing:(UITextField *)textField{
initialValueWhenEntering = [NSString stringWithString:textField.text];
[initialValueWhenEntering retain];
}
// This routine enforces that only a single period or numerics be taken into the new
// value for the input
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
unsigned int stringLength = (unsigned int)[textField.text lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
unsigned int counter;
unsigned int periodCounter = 0;
// Test to make sure there wasnt already some periods in the initial string
for(counter = 0; counter < stringLength; counter++){
if( [textField.text characterAtIndex:(NSUInteger)counter] != '.' &&
( [textField.text characterAtIndex:(NSUInteger)counter] < '0' ||
[textField.text characterAtIndex:(NSUInteger)counter] > '9' ) ){
return NO;
}else if( [textField.text characterAtIndex:(NSUInteger)counter] == '.' ){
periodCounter++;
}
}
stringLength = (unsigned int)[string lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
for(counter = 0; counter < stringLength; counter++){
if( [string characterAtIndex:(NSUInteger)counter] != '.' &&
( [string characterAtIndex:(NSUInteger)counter] < '0' || [string characterAtIndex:(NSUInteger)counter] > '9' ) ){
return NO;
}else if( [string characterAtIndex:(NSUInteger)counter] == '.' ){
periodCounter++;
}
}
if( periodCounter <= 1 ){
return YES;
}else{
return NO;
}
}
And finally the routine that gets automatically called when the textfield has ended editing
-(void)textFieldDidEndEditing:(UITextField *)textField{
unsigned int stringLength = (unsigned int)[textField.text
lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
unsigned int counter;
if( 0 == stringLength ){
textField.text = initialValueWhenEntering;
float temperature = [textField.text floatValue];
// Set the temperature of all element boxes
for(counter = MIN_ELEMENT_INDEX; counter <= MAX_ELEMENT_INDEX; counter++){
[periodicButtons[counter] setOutputType:myGraphType aValue:temperature];
}
}else if( 1 == stringLength ){
if( [textField.text characterAtIndex:(NSUInteger)0] == '.' ){
textField.text = initialValueWhenEntering;
}
float temperature = [textField.text floatValue];
textField.text = [NSString stringWithFormat:@"%.2f", temperature];
// Set the temperature of all element boxes
for(counter = MIN_ELEMENT_INDEX; counter <= MAX_ELEMENT_INDEX; counter++){
[periodicButtons[counter] setOutputType:myGraphType aValue:temperature];
}
}else{ // Should be a semi-valid number at this point
float temperature = [textField.text floatValue];
if( temperature > 5900.0 ){
temperature = 5900.0;
}
textField.text = [NSString stringWithFormat:@"%.2f", temperature];
// Set the temperature of all element boxes
for(counter = MIN_ELEMENT_INDEX; counter <= MAX_ELEMENT_INDEX; counter++){
[periodicButtons[counter] setOutputType:myGraphType aValue:temperature];
}
}
[initialValueWhenEntering release];
}
In my example, I did perform value limit checking, but this code could be deleted.