2012-06-26 3 views
5

私はUITextViewのサブクラスを持っています。私はそれを自分の代理人にしたいと思います。私がtextView:shouldChangeTextInRange:replacementText:メソッドをオーバーライドできるように、連続したスペースが入力されないようにしてください。UITextViewは無限ループを意味します。

[SATextView awakeFromNib](SATextViewはUITextViewのサブクラスです)では、私は[self setDelegate:self];です。私がtextviewを押すと、すべての編集が始まり、最終的には停止し、そのバックトレースは無限ループを示しています。

すべてのデリゲートメソッドを実装しても問題ありません。それらのメソッドが空であっても問題はありません。

なぜこれが無限ループを引き起こしますか? UITextView(他のオブジェクトをサブクラス化してデリゲートをselfに設定することができ、この問題は発生しません)の場合にのみ発生します。そしてどうすれば止めることができますか?または、このサブクラスが連続した空白を持つことができないようにするより良い方法があります。

+0

考えてみてください。ハード。クラスを独自の代理人にすることは可能ですが、考えが必要です。 –

+0

@HotLicks私はそれについても持っている、私は問題なく他のクラスでそれをやった?手伝ってくれますか? –

+0

バックトレースにはあなたのループが表示されるはずです。 –

答えて

1

アイデア...実際のデリゲートとUITextViewの中間の役割を果たすデリゲートクラスを作ることができます。しばらくしてからデリゲートを設定する必要があります)。したがって、この新しいクラスはデリゲートプロトコルを実装しますが、独自の代理人のためのプロパティも持ちますので、textView:shouldChangeTextInRange:replacementText:を引き渡し、middleManクラスのスペースを編集する作業を行います。

+0

と呼ぶ必要があります。これは私が推奨するものです。 'UITextViewDelegate'を実装するヘルパークラスを作成し、必要な振る舞いを強制します。このクラスは、必要に応じて、全体のロジックを管理するコントローラにメッセージを送信するために、独自のプロトコルを持つことができます。このパターンは多くのシナリオで役に立ちます。私は 'UITableViewDataSource'にもこのパターンを使用しています。あなたはすてきで整然とした、再利用可能なプロトコルの実装に終わります。 – XJones

0

オブジェクトに任意の数のオブザーバーをサブスクライブできます。したがって、それ自体を購読することが可能です:

@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:@" "]; 
} 
+1

ありがとうございますが、通知センターを使って見ることができない 'should'メソッドが必要です –

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 

一つの大きな「落とし穴は、」私は_externalDelegateを返すようにdelegateを上書きしようとしていたしましたが、それはいくつかの奇妙な副作用を引き起こした(返される実際のデリゲートに依存して内部のコードが存在しなければなりません)。