BTUIKTextField.m 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #import "BTUIKTextField.h"
  2. #import "BTUIKInputAccessoryToolbar.h"
  3. #import "BTUIKAppearance.h"
  4. #import "BTUIKViewUtil.h"
  5. @interface BTUIKTextField () <UITextFieldDelegate>
  6. @property (nonatomic, copy) NSString *previousText;
  7. @end
  8. @implementation BTUIKTextField
  9. - (instancetype)init {
  10. if (self = [super init]) {
  11. self.hideCaret = NO;
  12. if ([UIDevice currentDevice].systemVersion.intValue == 9) {
  13. [self addTarget:self action:@selector(iOS9_changed) forControlEvents:UIControlEventEditingChanged];
  14. self.delegate = self;
  15. }
  16. }
  17. return self;
  18. }
  19. - (void)setPlaceholder:(NSString *)placeholder {
  20. NSMutableAttributedString *mutablePlaceholder = [[NSMutableAttributedString alloc] initWithString:placeholder];
  21. [mutablePlaceholder beginEditing];
  22. [mutablePlaceholder addAttributes:@{NSForegroundColorAttributeName: [BTUIKAppearance sharedInstance].placeholderTextColor,
  23. NSFontAttributeName:[[BTUIKAppearance sharedInstance].font fontWithSize:UIFont.labelFontSize]}
  24. range:NSMakeRange(0, [mutablePlaceholder length])];
  25. [mutablePlaceholder endEditing];
  26. self.attributedPlaceholder = mutablePlaceholder;
  27. }
  28. - (void)iOS9_changed {
  29. // We only want to notify when this text field's text length has increased
  30. if (self.previousText.length >= self.text.length) {
  31. self.previousText = self.text;
  32. return;
  33. }
  34. self.previousText = self.text;
  35. NSString *insertedText = [self.text substringWithRange:NSMakeRange(self.previousText.length, self.text.length - self.previousText.length)];
  36. if ([self.editDelegate respondsToSelector:@selector(textField:willInsertText:)]) {
  37. // Sets _backspace = NO; in the BTUIKFormField or BTUIKFormField subclass
  38. [self.editDelegate textField:self willInsertText:insertedText];
  39. }
  40. self.previousText = self.text;
  41. if ([self.editDelegate respondsToSelector:@selector(textField:didInsertText:)]) {
  42. [self.editDelegate textField:self didInsertText:insertedText];
  43. }
  44. }
  45. - (BOOL)keyboardInputShouldDelete:(__unused UITextField *)textField {
  46. if ([self.editDelegate respondsToSelector:@selector(textFieldWillDeleteBackward:)]) {
  47. [self.editDelegate textFieldWillDeleteBackward:self];
  48. }
  49. BOOL shouldDelete = YES;
  50. if ([UITextField instancesRespondToSelector:_cmd]) {
  51. BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd];
  52. if (keyboardInputShouldDelete) {
  53. shouldDelete = keyboardInputShouldDelete(self, _cmd, textField);
  54. }
  55. }
  56. BOOL isIos8 = ([[[UIDevice currentDevice] systemVersion] intValue] == 8);
  57. BOOL isLessThanIos8_3 = ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.3f);
  58. // iOS 8.0-8.2 has a bug where deleteBackward is not called even when this method returns YES and the character is deleted
  59. // As a result, we do so manually but return NO in order to prevent UITextField from double-calling the delegate method
  60. // (textFieldDidDeleteBackwards:originalText:)
  61. if (isIos8 && isLessThanIos8_3) {
  62. [self deleteBackward];
  63. shouldDelete = NO;
  64. }
  65. return shouldDelete;
  66. }
  67. - (void)deleteBackward
  68. {
  69. BOOL shouldDismiss = [self.text length] == 0;
  70. NSString *originalText = self.text;
  71. [super deleteBackward];
  72. if (shouldDismiss) {
  73. if ([self.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
  74. [self.delegate textField:self shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""];
  75. }
  76. }
  77. if ([self.editDelegate respondsToSelector:@selector(textFieldDidDeleteBackward:originalText:)]) {
  78. [self.editDelegate textFieldDidDeleteBackward:self originalText:originalText];
  79. }
  80. }
  81. - (void)insertText:(NSString *)text {
  82. if ([self.editDelegate respondsToSelector:@selector(textField:willInsertText:)]) {
  83. [self.editDelegate textField:self willInsertText:text];
  84. }
  85. [super insertText:text];
  86. if ([self.editDelegate respondsToSelector:@selector(textField:didInsertText:)]) {
  87. [self.editDelegate textField:self didInsertText:text];
  88. }
  89. }
  90. - (CGRect)caretRectForPosition:(UITextPosition *)position
  91. {
  92. if (self.hideCaret) {
  93. return CGRectZero;
  94. }
  95. return [super caretRectForPosition:position];
  96. }
  97. @end