2525
2626@interface FUICodeField ()
2727
28- @property (nonatomic , retain , readonly ) UIView *inputField;
29-
30- @property (weak , nonatomic ) IBOutlet UILabel *digits;
31-
32- @property (nonatomic , readonly ) IBInspectable NSString *placeholder;
28+ @property (nonatomic , readonly ) IBInspectable NSString *placeholderChar;
3329
3430@end
3531
3632@implementation FUICodeField
3733
3834- (instancetype )initWithFrame : (CGRect)frame {
3935 if (self = [super initWithFrame: frame]){
40- [self setUpFromNib ];
36+ [self commonInit ];
4137 }
4238 return self;
4339}
4440
4541- (nullable instancetype )initWithCoder : (NSCoder *)aDecoder {
4642 if (self = [super initWithCoder: aDecoder]){
47- [self setUpFromNib ];
43+ [self commonInit ];
4844 }
4945 return self;
5046}
5147
52- - (void )setUpFromNib {
53- NSBundle *bundle = [FUIAuthUtils bundleNamed: FUIPhoneAuthBundleName];
54- UINib *nib = [UINib nibWithNibName: NSStringFromClass ([self class ]) bundle: bundle];
55-
56- _inputField = [nib instantiateWithOwner: self options: nil ][0 ];
57- self.inputField .frame = [self bounds ];
58- self.inputField .autoresizingMask =
59- UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
60- self.inputField .userInteractionEnabled = YES ;
61-
62- if (@available (iOS 12.0 , *)) {
63- if ([self .inputField respondsToSelector: @selector (setTextContentType: )]) {
64- id <UITextInputTraits> inputField = (id <UITextInputTraits>)self.inputField ;
65- inputField.textContentType = UITextContentTypeOneTimeCode;
66- }
67- }
68-
48+ - (void )commonInit {
6949 // Initialization code
7050 _codeEntry = [NSMutableString string ];
51+ self.backgroundColor = UIColor.clearColor ;
52+ self.tintColor = UIColor.clearColor ;
53+ self.font = [UIFont fontWithName: @" Courier" size: 40 ];
54+ self.textAlignment = NSTextAlignmentLeft;
55+ UIView *paddingView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 20 , self .bounds.size.height)];
56+ self.leftView = paddingView;
57+ self.leftViewMode = UITextFieldViewModeAlways;
58+ self.textContentType = UITextContentTypeOneTimeCode;
7159
7260 // Default values
7361 if (!self.codeLength ) {
@@ -76,11 +64,12 @@ - (void)setUpFromNib {
7664 _codeLength = MIN (self.codeLength , 12 );
7765 }
7866
79- if (!self.placeholder || !self.placeholder .length ) {
80- _placeholder = @" -" ;
67+ if (!self.placeholderChar || !self.placeholderChar .length ) {
68+ _placeholderChar = @" -" ;
8169 }
8270
83- [self addSubview: self .inputField];
71+ self.delegate = self;
72+ [self updateText ];
8473}
8574
8675- (UIKeyboardType) keyboardType {
@@ -91,38 +80,6 @@ - (UIKeyboardType) keyboardType {
9180 }
9281}
9382
94- - (BOOL )canBecomeFirstResponder {
95- return YES ;
96- }
97-
98- - (void ) touchesBegan : (NSSet *) touches withEvent : (nullable UIEvent *) event {
99- [self becomeFirstResponder ];
100- }
101-
102- - (void )drawRect : (CGRect)rect {
103- NSString *code = [self .codeEntry copy ];
104- if (self.secureTextEntry ) {
105- code = [[NSString string ] stringByPaddingToLength: code.length
106- withString: @" \u2022 " startingAtIndex: 0 ];
107- }
108-
109- NSInteger add = self.codeLength - code.length ;
110- if (add > 0 ) {
111- NSString *pad = [[NSString string ] stringByPaddingToLength: add
112- withString: self .placeholder
113- startingAtIndex: 0 ];
114- code = [code stringByAppendingString: pad];
115- }
116-
117- NSMutableAttributedString *attributedString =
118- [[NSMutableAttributedString alloc ] initWithString: code];
119- [attributedString addAttribute: NSKernAttributeName value: @20
120- range: NSMakeRange (0 , attributedString.length-1 )];
121-
122- self.digits .text = @" " ;
123- [self .digits setAttributedText: attributedString];
124- }
125-
12683- (BOOL )hasText {
12784 return self.codeEntry .length > 0 ;
12885}
@@ -131,63 +88,69 @@ - (void)insertText:(NSString *)theText {
13188 if (self.codeEntry .length >= self.codeLength ){
13289 // UX: if code was submitted and there is an error message,
13390 // typing a new number should clear the field and start over
91+ [self updateText ];
13492 return ;
13593 }
13694
13795 [self .codeEntry appendString: theText];
138- [self setNeedsDisplay ];
96+ [self updateText ];
13997 [self notifyEntryCompletion ];
14098}
14199
142100- (void )deleteBackward {
143- if (!self.codeEntry .length ){
101+ if (!self.codeEntry .length ) {
144102 return ;
145103 }
146104
147- NSRange theRange = NSMakeRange (self.codeEntry .length - 1 , 1 );
105+ NSRange theRange = NSMakeRange (self.codeEntry .length - 1 , 1 );
148106 [self .codeEntry deleteCharactersInRange: theRange];
149- [self setNeedsDisplay ];
107+ [self updateText ];
150108 [self notifyEntryCompletion ];
151109}
152110
153111- (void )clearCodeInput {
154112 [self .codeEntry setString: @" " ];
155-
156- [self setNeedsDisplay ];
113+ [self updateText ];
157114 [self notifyEntryCompletion ];
158115}
159116
160117- (void )notifyEntryCompletion {
161118 if (self.codeEntry .length >= self.codeLength ) {
162- [self .delegate entryIsCompletedWithCode: [self .codeEntry copy ]];
119+ [self .codeDelegate entryIsCompletedWithCode: [self .codeEntry copy ]];
163120 } else {
164- [self .delegate entryIsIncomplete ];
121+ [self .codeDelegate entryIsIncomplete ];
165122 }
166123}
167124
168- - (CGSize)inputFieldIntrinsicContentSize {
169- CGSize textFieldSize = [self .inputField intrinsicContentSize ];
170- if (textFieldSize.height < FUICodeFieldMinInputFieldHeight) {
171- textFieldSize.height = FUICodeFieldMinInputFieldHeight;
172- }
173-
174- return textFieldSize;
175- }
125+ - (void )updateText {
126+ NSString *code = [self .codeEntry copy ];
127+ if (self.secureTextEntry ) {
128+ code = [[NSString string ] stringByPaddingToLength: code.length
129+ withString: @" \u2022 " startingAtIndex: 0 ];
130+ }
176131
177- - (CGSize)intrinsicContentSize {
178- CGSize textFieldSize = [self inputFieldIntrinsicContentSize ];
179- return textFieldSize;
180- }
132+ NSInteger add = self.codeLength - code.length ;
133+ if (add > 0 ) {
134+ NSString *pad = [[NSString string ] stringByPaddingToLength: add
135+ withString: self .placeholderChar
136+ startingAtIndex: 0 ];
137+ code = [code stringByAppendingString: pad];
138+ }
181139
182- - (UITextContentType _Null_unspecified) textContentType {
183- if (@ available (iOS 12.0 , *)) {
184- return UITextContentTypeOneTimeCode;
185- }
186- return nil ;
140+ NSMutableAttributedString *attributedString =
141+ [[ NSMutableAttributedString alloc ] initWithString: code];
142+ [attributedString addAttribute: NSKernAttributeName value: @ 20
143+ range: NSMakeRange ( 0 , attributedString.length - 1 )];
144+ self. attributedText = attributedString ;
187145}
188146
189- - (void )setTextContentType : (_Null_unspecified UITextContentType)textContentType {
190- // do nothing
147+ - (BOOL )textField : (UITextField *)textField shouldChangeCharactersInRange : (NSRange )range replacementString : (NSString *)string {
148+ if (string.length == 0 ) {
149+ [self deleteBackward ];
150+ } else {
151+ [self insertText: string];
152+ }
153+ return false ;
191154}
192155
193156@end
0 commit comments