简体   繁体   English

textField:shouldChangeCharactersInRange:replacementString:in subclass

[英]textField:shouldChangeCharactersInRange:replacementString: in subclass

I've subclassed a UITextField and I'd like to use a method similar to textField:shouldChangeCharactersInRange:replacementString: inside the subclass to get notified when a character is typed and if necessary block the change, but avoid setting the fields delegate to itself. 我已经将UITextField子类化了,我想使用类似于textField:shouldChangeCharactersInRange:replacementString:的方法textField:shouldChangeCharactersInRange:replacementString:在子类内部获取通知,当键入字符并且必要时阻止更改,但避免将字段委托给自己。

I've found if I override keyboardInput:shouldInsertText:isMarkedText: and keyboardInputShouldDelete: I can get the desired effect, unfortunately these methods are private and anything using the class won't make it through the App Store submission process. 我发现如果我覆盖keyboardInput:shouldInsertText:isMarkedText:keyboardInputShouldDelete:我可以得到所需的效果,不幸的是这些方法是私有的,任何使用该类的东西都不会通过App Store提交过程。

Anyone know of a public method that achieves the same thing and doesn't require the field being its own delegate? 任何人都知道一个公共方法实现同样的事情,并不要求该字段是自己的委托?

UPDATE: 更新:

I went with the suggestion of creating a separate object just to be the delegate, which itself can have a delegate to forward messages to. 我接着建议创建一个单独的对象只是作为委托,它本身可以有一个委托来转发消息。

在尝试过UITextField的子类之前,我已经学会了避免这种情况并转而使用委托路径(它有一个类似的方法叫- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string ,应该做我认为你已经描述过的)。

One strategy to explore here is to override the setDelegate: method and then do some message forwarding. 这里要探索的一个策略是覆盖setDelegate:方法然后执行一些消息转发。 You can use [super setDelegate: self] to make sure your calls gets first dibs at the delegate messages. 您可以使用[super setDelegate: self]来确保您的调用在委托消息中获得第一个[super setDelegate: self] In your override of setDelegate: set an internal ivar, eg 在你的setDelegate重写中:设置一个内部的ivar,例如

 - (void) setDelegate: (id<UITextFieldDelegate>) internalDelegate;
 {
     [setInternalDelegate: internalDelegate];
 }

Then for each of the the UITextField delegate methods do your thing before forwarding on the delegate message, eg 然后,对于每个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];
}

Typically, you'll want to override all of the delegate methods, even if for most of them all you do is a straight forward. 通常,您将要覆盖所有委托方法,即使对于大多数委托方法,您只需要直接进行。

Update You note in comments that the forwarding approach is raising issues. 更新您在评论中注意到转发方法引发了问题。 If so, then traditional delegation is the way to go. 如果是这样,那么传统的授权就是可行的方式。 (And, in generally, it is the way to go - although I've used forwarding delegate once or twice, I'm not sure if, with hindsight, it was absolutely essential and I've not checked to see if I've done it with UITextField. @ Scott Corscadden has and does not recommend it.) (而且,一般情况下,它要走的路 - 尽管我曾经使用过一次或两次转发代表,但我不确定,事后来看,它是绝对必要的,而且我没有检查过我是否已经用UITextField完成。@ Scott Corscadden已经并且不推荐它。)

The most common pattern is to make the ViewController that looks after the view in which the UITextField is a subview the delegate. 最常见的模式是使ViewController能够查看UITextField是子视图的视图。 You don't say in your answer if there's particular reason why you need to work with the subclass. 如果您需要使用子类的特殊原因,您在答案中没有说。 If you're packing interesting stuff into the UITextField then it might be, though you could always another poster suggests and create a companion class for UITextField that does that work and use that as the delegate. 如果你正在将有趣的东西打包到UITextField那么它可能是,尽管你可能总是另一张海报建议并为UITextField创建一个伴侣类来完成这项工作并将其用作委托。 In any case, if need be, you can always get the delegate object to call extra methods on your UITextField subclass, eg 在任何情况下,如果需要,您总是可以让委托对象在您的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...
}

You may play with Objective-C runtime to achieve this. 您可以使用Objective-C运行时来实现此目的。 The following code is working for me. 以下代码对我有用。 The idea is: 这个想法是:

  • in subclass we set delegate property to self; 在子类中,我们将delegate属性设置为self;
  • we override setDelegate: method in which we store supplied delegate to a variable ( forwardDelegate ); 我们覆盖setDelegate:方法,我们将提供的委托存储到变量( forwardDelegate );
  • by overriding respondsToSelector: , forwardInvocation: and methodSignatureForSelector: we either call method on self or forward it to saved forwardDelegate . 通过重写respondsToSelector:forwardInvocation:methodSignatureForSelector:我们要么在self上调用方法,要么将它转发给已保存的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

You can use the delegate method of the uitextfield, 你可以使用uitextfield的委托方法,

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{

}

And don't forget to set your textfield.delegate = self in ViewDidLoad. 并且不要忘记在ViewDidLoad中设置textfield.delegate = self

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 文本框:shouldChangeCharactersInRange:replacementString: - textField:shouldChangeCharactersInRange:replacementString: TextField:shouldChangeCharactersInRange:replacementString:返回陷阱! - TextField:shouldChangeCharactersInRange:replacementString: return trap! Xcode使用textField shouldChangeCharactersInRange:导致应用崩溃 - Xcode Using textField shouldChangeCharactersInRange: crashes app 编辑已更改可在IOS5中使用,但不能在IOS6中使用。 textField:shouldChangeCharactersInRange: - Editing Changed works in IOS5 but not IOS6. textField: shouldChangeCharactersInRange: 使用`textField:shouldChangeCharactersInRange:`,我如何发现字符不匹配? - Using `textField:shouldChangeCharactersInRange:`, how do i found that characters are mismatch? UITextField shouldChangeCharactersInRange - UITextField shouldChangeCharactersInRange 应该带有特殊分隔符的ChangeChangedCharactersInRange - shouldChangeCharactersInRange with special separation UITextField shouldChangeCharactersInRange委托不起作用 - UITextField shouldChangeCharactersInRange Delegate not working 无法用shouldChangeCharactersInRange隐藏键盘 - Can't hide the keyboard with shouldChangeCharactersInRange UITextField shouldChangeCharactersInRange输入A到B之间的值 - UITextField shouldChangeCharactersInRange enter value Between A to B
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM