我知道互联网上有很多关于这个问题的信息,但我被卡住了。我有一个应用程序,我需要在其中自定义我的 UITextFields
.例如,我需要在编辑开始时更改边框颜色,或者我需要限制可以在不同文本字段中设置的字符数。我还需要在几个必须在左侧缩进的文本字段中的图像。为此,我决定创建自定义 UITextField 类(作为 UITextField 的子类)。我从 UITextField
创建了新类(实现 <UITextFieldDelegate>
)。在那个课上我使用 self.delegate = self
(这在互联网上被广泛使用,人们说它有效)所以我可以实现 shouldChangeCharactersInRange
或 textFieldShouldBeginEditing
在我的自定义类中。我的问题是,在此配置中,我收到无限循环和应用程序重启(请参阅 my question 关于)。这来自self.delegate = self
.我知道在某些情况下我可以使用 observer
但在那种情况下我该如何实现 shouldChangeCharactersInRange
在我类里?
如果我不以这种方式实现我的类并将我的文本字段委托(delegate)给我的 View Controller 。我必须在我的 View Controller 类中实现所有这些方法,在我看来这是非常难看的解决方案。
所以我的问题是如何正确实现 UITextField 子类?
附言我想我是以错误的方式做的,但我无法弄清楚哪个是正确的。
编辑:
这是我的代码:
MyCustomTextField.h
@interface MyCustomTextField : UITextField
@property (nonatomic) int maxSymbols;
@property (nonatomic) int leftIndent;
@end
MyCustomTextField.m
@interface MyCustomTextField () <UITextFieldDelegate>
@end
@implementation MyCustomTextField
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]) {
self.delegate = self;
self.clipsToBounds = YES;
[self setLeftViewMode:UITextFieldViewModeAlways];
UIImageView *imageView1 = [[UIImageView alloc]
initWithFrame:CGRectMake(0, 0, 37, 20)];
imageView1.image = [UIImage imageNamed:@"otp_back"];
self.leftView = imageView1;
}
return self;
}
- (CGRect) leftViewRectForBounds:(CGRect)bounds {
CGRect textRect = [super leftViewRectForBounds:bounds];
textRect.origin.x = 5;
return textRect;
}
还有这种检查最大长度的方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// Restrict number of symbols in text field to "maxSymbols"
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
BOOL returnKey = [string rangeOfString: @"\n"].location != NSNotFound;
return newLength <= (int)_maxSymbols || returnKey;
}
当我转到文本字段并开始从模拟器的虚拟键盘键入时,我收到无限循环并以 BAD ACCESS 退出。这很奇怪,因为如果键盘是数字或密码类型,或者如果我从 Mac 键盘输入,我没有收到问题。
最佳答案
我不同意一直在 View Controller 中设置委托(delegate)。使用 UITextField 本身作为委托(delegate)有几个明显的优势,例如当许多不同的 View Controller 共享相同的文本字段行为时代码更清晰。
在 iOS 8 中,自委托(delegate)引用循环似乎是“固定的”。但对于那些针对 iOS 7 及以下版本的用户,我们使用代理对象来绕过循环:
InputTextProxy.h:
@interface InputTextProxy : NSObject <UITextFieldDelegate>
@property (weak, nonatomic) id<UITextFieldDelegate> proxiedDelegate;
@end
InputTextProxy.m:
#import "InputTextProxy.h"
@implementation InputTextProxy
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [self.proxiedDelegate textFieldShouldReturn:textField];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return [self.proxiedDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
}
@end
您可以根据需要添加更多回调,我们只使用以上两个。
现在在您的子类 MyCustomTextField.m 中创建一个属性:
@property (strong, nonatomic) InputTextProxy *inputProxy;
- (InputTextProxy *)inputProxy
{
if (!_inputProxy)
_inputProxy = [[InputTextProxy alloc] init];
return _inputProxy;
}
使用它来设置你的委托(delegate):
self.delegate = self.inputProxy;
self.inputProxy.proxiedDelegate = self;
关于ios - 如何在 iOS 中正确继承 UITextField?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25998600/