5

我有一个 UITextView 的子类,我想让它成为自己的代表。这样我就可以覆盖该textView:shouldChangeTextInRange:replacementText:方法,并防止输入连续的空格。

[SATextView awakeFromNib](SATextView 是我的 UITextView 的子类)中,我做[self setDelegate:self];. 当我按下 textview 开始编辑时,所有内容都冻结并最终停止,并且回溯显示存在无限循环。

如果我实现所有委托方法,只实现一个或没有,都没有关系。这些方法是否为空也没关系。

为什么这会导致无限循环?它似乎只有在使用 UITextView 时才会发生(您可以子类化其他对象并将委托设置为 self,它不会有这个问题)。我该如何阻止它?或者有没有更好的方法让这个子类不能有连续的空格,

4

3 回答 3

1

一个想法...您可以创建一个委托类,充当真正的委托和 UITextView 之间的中间人(因为您可能需要在一段时间后设置委托)。所以这个新类将实现委托协议,但它也将具有它自己的委托的属性,以便您可以转发 textView:shouldChangeTextInRange:replacementText:,并且仍然可以在中间人类中编辑空格。

于 2012-06-26T20:44:55.570 回答
0

It is possible to subscribe any numbers of observers to an object. So it is possible to subscribe itself:

@implementation MyTextView 

-(id) initWithFrame:(CGRect)frame // or initWithCoder: for loading from nib
{
    self = [super initWithFrame:frame];
    if(self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidChangeNotification:) name:UITextViewTextDidChangeNotification object:self];
    }
    return self;
}

-(void)textViewTextDidChangeNotification:(NSNotification*)n
{
    self.text = [self.text stringByReplacingOccurrencesOfString:@"  " withString:@" "];
}
于 2012-06-26T23:25:08.257 回答
0

这是我如何成功完成此操作的示例。我只对阻止输入某些字符感兴趣,所以我只实现textView:shouldChangeTextInRange:replacementText:然后传递其余的。

#import "INFTextView.h"

@interface INFTextView () <UITextViewDelegate>

@property (nonatomic, weak) id<UITextViewDelegate> externalDelegate;

@end

@implementation INFTextView

- (id)init {
    self = [super init];
    if (!self) {
        return nil;
    }

    self.delegate = self;

    return self;
}

- (void)awakeFromNib {
    self.delegate = self;
}

- (void)setDelegate:(id<UITextViewDelegate>)delegate {
    // we always want self to be the delegate, if someone is interested in delegate calls we will forward those on if applicable
    if (delegate == self) {
        [super setDelegate:self];
        return;
    } else {
        // capture that someone else is interested in delegate calls
        _externalDelegate = delegate;
    }
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSCharacterSet *unsupportedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:kINFSupportedCharacters] invertedSet];

    NSRange unsupportedCharacterRange = [text rangeOfCharacterFromSet:unsupportedCharacterSet];
    if (unsupportedCharacterRange.location == NSNotFound) {
        return YES;
    } else {
        return NO;
    }
}

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewShouldBeginEditing:)]) {
        return [_externalDelegate textViewShouldBeginEditing:textView];
    }

    return YES;
}

- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewShouldEndEditing:)]) {
        return [_externalDelegate textViewShouldEndEditing:textView];
    }

    return YES;
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewDidBeginEditing:)]) {
        [_externalDelegate textViewDidBeginEditing:textView];
    }
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewDidEndEditing:)]) {
        [_externalDelegate textViewDidEndEditing:textView];
    }
}

- (void)textViewDidChange:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewDidChange:)]) {
        [_externalDelegate textViewDidChange:textView];
    }
}

- (void)textViewDidChangeSelection:(UITextView *)textView {
    if ([_externalDelegate respondsToSelector:@selector(textViewDidChangeSelection:)]) {
        [_externalDelegate textViewDidChangeSelection:textView];
    }
}

@end

导致我提出这个问题的一个大“问题”是我试图覆盖delegate返回_externalDelegate,但这会导致一些奇怪的副作用(必须有内部代码取决于要返回的实际委托)。

于 2013-08-21T21:31:43.403 回答