我已经将UITextField子类化了,我想在子类中使用类似于textField:shouldChangeCharactersInRange:replacementString:
的方法,以便在输入字符时获得通知,并在必要时阻止更改,但是避免将字段委托给本身。
我发现如果我覆盖keyboardInput:shouldInsertText:isMarkedText:
和keyboardInputShouldDelete:
我可以获得所需的效果,不幸的是这些方法是私有的,使用该类的任何内容都无法通过App Store提交过程。
任何人都知道一个公共方法可以达到同样的目的,并且不需要该字段是自己的委托吗?
更新
我接着建议创建一个单独的对象作为委托,它本身可以有一个委托来转发消息。
答案 0 :(得分:2)
之前尝试过UITextField的子类,我已经学会了避免这种情况并转而使用委托路径(它有一个类似的方法叫做- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
,应该做我认为你所描述的)。
答案 1 :(得分:2)
这里要探索的一个策略是覆盖setDelegate:方法然后执行一些消息转发。您可以使用[super setDelegate: self]
确保您的呼叫在委派消息中获得第一个dib。在你的setDelegate重写中:设置一个内部的ivar,例如
- (void) setDelegate: (id<UITextFieldDelegate>) internalDelegate;
{
[setInternalDelegate: internalDelegate];
}
然后,对于每个UITextField委托方法,在转发委托消息之前执行您的操作,例如
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
{
// do your thing with range and replacement string
// now forward message on the 'other' delegate
[[self internalDelegate] textField: self shouldChangeCharactersInRange: range replacementString: string];
}
通常情况下,您需要覆盖所有委托方法,即使大多数委托方法都是直接的。
更新您在评论中注意到转发方法引发了问题。如果是这样,那么传统的授权就是可行的方式。 (而且,一般情况下,它是的方式 - 虽然我曾经使用过一次或两次转发代表,但我不确定,事后来看,它是绝对必要的而且我没有检查我是否使用UITextField完成了它。@ Scott Corscadden有并且不推荐它。)
最常见的模式是使ViewController能够查看UITextField
是子视图的视图。如果您需要使用子类的特殊原因,您在答案中没有说。如果你正在将有趣的东西打包到UITextField
中,那么它可能是,尽管你可能总是另一张海报建议并为UITextField
创建一个伴侣类来完成这项工作并将其用作委托。在任何情况下,如果需要,您总是可以让委托对象在UITextField
子类上调用额外的方法,例如
// in the delegate object class
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
{
[delegate doSomeExtraThingInTheTextFieldSubclassThatItSeemsToMakeSenseToDoThereRatherThanHere];
// maybe that's it, or maybe this object also wants to do something here...
}
答案 2 :(得分:1)
您可以使用Objective-C运行时来实现此目的。以下代码对我有用。 这个想法是:
delegate
属性设置为self; setDelegate:
方法,我们将提供的委托存储到变量(forwardDelegate
); respondsToSelector:
,forwardInvocation:
和methodSignatureForSelector:
,我们可以自行调用方法或将其转发给已保存的forwardDelegate
。// MyTextField.h
@interface MyTextField : UITextField
@end
// MyTextField.m
@interface MyTextField () <UITextFieldDelegate>
@end
@implementation MyTextField {
id forwardDelegate;
}
- (void) myTextFieldCommonInit
{
[super setDelegate:self];
}
- (id) initWithCoder:(NSCoder *)coder
{
if ((self = [super initWithCoder:coder])) {
[self myTextFieldCommonInit];
}
return self;
}
- (id) initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
[self myTextFieldCommonInit];
}
return self;
}
- (void) setDelegate:(id)delegate
{
forwardDelegate = delegate;
}
- (BOOL) respondsToSelector:(SEL)selector
{
if ([super respondsToSelector:selector]) {
return YES;
} else {
return [forwardDelegate respondsToSelector:selector];
}
}
- (void) forwardInvocation:(NSInvocation *)invocation
{
if ([super respondsToSelector:[invocation selector]]) {
[super forwardInvocation:invocation];
} else if ([forwardDelegate respondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:forwardDelegate];
} else {
[self doesNotRecognizeSelector:[invocation selector]];
}
}
- (NSMethodSignature *) methodSignatureForSelector:(SEL)selector
{
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
if (signature) {
return signature;
} else {
return [forwardDelegate methodSignatureForSelector:selector];
}
}
#pragma mark - UITextFieldDelegate
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
...
}
@end
答案 3 :(得分:0)
您可以使用uitextfield的委托方法
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
}
不要忘记在ViewDidLoad中设置textfield.delegate = self
。