ios - 如何在 iOS 中正确继承 UITextField?

标签 ios objective-c uitextfield

我知道互联网上有很多关于这个问题的信息,但我被卡住了。我有一个应用程序,我需要在其中自定义我的 UITextFields .例如,我需要在编辑开始时更改边框颜色,或者我需要限制可以在不同文本字段中设置的字符数。我还需要在几个必须在左侧缩进的文本字段中的图像。为此,我决定创建自定义 UITextField 类(作为 UITextField 的子类)。我从 UITextField 创建了新类(实现 <UITextFieldDelegate> )。在那个课上我使用 self.delegate = self (这在互联网上被广泛使用,人们说它有效)所以我可以实现 shouldChangeCharactersInRangetextFieldShouldBeginEditing在我的自定义类中。我的问题是,在此配置中,我收到无限循环和应用程序重启(请参阅 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/

相关文章:

objective-c - 为什么 setDelegate 不适用于 UITextFieldDelegate,而是通过 Interface Builder 工作

ios - TextView和TextField的单个扩展以添加工具栏

ios - 如何在 Swift 中禁用 "Join Wi-Fi network"警报消息?

ios - 无法阻止 Sprite 移出屏幕

objective-c - 多线程和自动释放池

ios - 根据输入的字符限制 UITextField 在用户输入时显示的内容

ios - MKAnnotationView : have texts below the annotationView and render the View

iOS JSON 解析

IOS 9 NSURLConnection 弃用

objective-c - 重复一次后停止动画