Reputation: 3970
I just made a formatter class that will automatically format numbers typed into a uitextfield and give back the correct format.
i.e.
Text field will look like this $0.00
if you type 1,2,3,a,b,c you get $1.23 in the text field.
I did this by making a custom class that was a UITextfieldDelegate and responded to the textfields delegate methods.
However my viewcontroller also needs to respond to when the text changes in this text field.
Can I have to delegates? Or am I going to have to make my formatter class have a delegate method also?
Upvotes: 1
Views: 3064
Reputation: 14427
I realize I am a little late to this party, but why not just add the CustomDelegate class to your VC in Interface Builder and set the delegate for the UITextField
to that? No extra code in the VC is required, no UITextField
subclassing is needed either. Project link below that does this to custom format a phone number.
Link to example project This link will go away when I decide it will go away. It could live on here forever (or as long as Dropbox is in business).
Added code example of the delegate class (although if someone had any amount of experience in iOS development, this wouldn't be needed.) That screenshot explains just about all of the answer. Example project link added as a convenience.
Code from the Delegate class:
Header File:
#import <Foundation/Foundation.h>
@interface PhoneNumberFormatterDelegate : NSObject <UITextFieldDelegate>
@end
Implementation File:
#import "PhoneNumberFormatterDelegate.h"
@implementation PhoneNumberFormatterDelegate
#pragma mark - My Methods
-(void)textFieldDidChange:(UITextField *)textField {
if ([textField.text length] > 11) {
[textField resignFirstResponder];
}
}
#pragma mark - UITextField Delegate Methods
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// If user hit the Done button, resign first responder
if([string isEqualToString:@"\n"]){
[textField resignFirstResponder];
return NO;
}
// All digits entered
if (range.location == 12) {
[textField resignFirstResponder];
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;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[textField removeTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
@end
Upvotes: 0
Reputation: 3222
I also propose that you use a NSNotificationCenter
for such a situation since you can't use two delegates, and here is an example of how to use NSNotificationCenter
.
Upvotes: 1
Reputation: 3970
The way I solved this was to make a class method that would return the correctly formatted the string.
Then I kept the delegation to the viewController.
When it asks should the text field change. I simply set the text using my class method and then return no so that it essentially ignores the users input.
Upvotes: 1
Reputation:
No, you can't have two delegates at once, it's one property, if you assign it for the second time, the first delegate will stop being a delegate. What you could do is make a common delegate class, where you set up an NSNotificationCenter to send notifications corresponding to the UITextField's events, and then register all your classes (which have to receive these events) to the NSNotificationCenter.
Upvotes: 0