1

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?

Hackmodford
  • 3,901
  • 4
  • 35
  • 78

4 Answers4

1

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.

Hackmodford
  • 3,901
  • 4
  • 35
  • 78
  • See my answer. In my opinion, a cleaner way to do it. – LJ Wilson Apr 11 '13 at 19:01
  • 1
    My answer required one line of code when all said and done ;) But to each his own... – Hackmodford Apr 15 '13 at 16:36
  • True. I have a project where I need to be doing that in several VC's and just wanted to be able to wire up the delegate to the textfields that needed special formatting and have no extra code in the VC. I have used your method in the past also. Both are efficient. – LJ Wilson Apr 15 '13 at 16:52
1

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.

Community
  • 1
  • 1
antf
  • 3,162
  • 2
  • 26
  • 33
0

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.

0

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

IB Screenshot

LJ Wilson
  • 14,445
  • 5
  • 38
  • 62
  • Sorry, this isn't really an answer. That dropbox link will die soon, rendering this useless. Try throwing it up on git, then [edit] this (and other copies I've removed), and change the link. There will still be a chance of deletion, however, depending on the community's reaction to your answer. To prevent this, also include relevant code snips from the solution. –  Apr 11 '13 at 19:38
  • I've looked this over, and the deletion here had nothing to do with inexperience in the iOS development environment. First, you pasted this same answer on three different questions, when it didn't specifically address the needs of two of them. These answers were being flagged for this. Second, we have indeed had problems with many DropBox links expiring and rendering answers useless, so any project contained there needs to be a supplement to what's presented in the answer. You've added sufficient detail to this that it does stand on its own now. – Brad Larson Apr 12 '13 at 16:22
  • That said, I'm not quite sure how this addresses the question asked here. They wanted to have their view controller respond to input from the text field, as well as being able to maintain the formatting. Doing the actual formatting wasn't their question. Your solution would not allow for the view controller to be updated as a direct delegate of the text field, because your formatter doesn't inform the view controller of changes. – Brad Larson Apr 12 '13 at 16:26
  • Actually, it does inform the VC of changes as it is the direct delegate to the TextField (that the VC owns). I believe the OP wanted to know how to assign a custom delegate in addition to the VC being the delegate. My answer explains that this is not a good design and that assigning the TextField directly to a custom delegate class is a better design pattern to use and accomplishes the goal of custom formatting in a design pattern that is easily re-used. – LJ Wilson Apr 12 '13 at 16:50
  • Thx @BradLarson for undeleting the answer BTW. The reason I stated that inexperience played a role is that in reality, the screenshot provided the meat of the answer and could stand on its own. How the custom delegate class is coded is extraneous to the answer as the OP already seemed to have knowledge on how to handle the various delegate methods he needed. – LJ Wilson Apr 12 '13 at 16:53
  • I guess I'm still not following you. The UITextField's delegate is your custom class, which manages the formatting, not the view controller. That formatter class alone will receive update messages from your UITextField. How are update messages going to get to your view controller? – Brad Larson Apr 12 '13 at 17:02
  • Well, the VC owns the UITextField. When the TextField's delegate methods are invoked (shouldReplaceCharacters.., etc) the updates are going to be visible in the TextField that the VC owns and displays. I am not near as savvy as you are, so I think we may not be talking about the same thing. My point is that the VC's TextField will show the formatted string being handled in the custom delegate. Am I missing your question? – LJ Wilson Apr 12 '13 at 17:12
  • @LJWilson The asker wanted the VC to receive a **notification** when the text field contents changed. In your solution, the updates are visible to the VC, but the VC won't be able to respond to the updates because there is no code in the VC that runs when the text changes. Sure, at some point in the future if some code in the VC gets invoked by some other event, then the VC can check the contents of the field; but that doesn't satisfy what the asker specified. – stone Jun 09 '15 at 06:32