2012-06-26 13 views
5

Ho una sottoclasse di UITextView e vorrei impostarlo come se fosse un suo delegato. In modo che io possa ignorare il metodo textView:shouldChangeTextInRange:replacementText: e impedire l'inserimento di spazi consecutivi.UITextView come proprio delegato significa loop infinito

In [SATextView awakeFromNib] (SATextView è la mia sottoclasse di UITextView), faccio [self setDelegate:self];. Quando premo sul textview per iniziare a modificare tutto si blocca e alla fine si arresta, e quel backtrace mostra che c'è stato un ciclo infinito.

Non importa se implemento tutti i metodi delegati, solo uno o nessuno. Né importa se quei metodi sono vuoti.

Perché questo causa un ciclo infinito? Sembra solo che accada se con UITextView (altri oggetti è possibile creare sottoclasse e impostare il delegato su se stesso, e non avrà questo problema). E come posso fermarlo? O c'è un modo migliore per avere questa sottoclasse non in grado di avere spazi consecutivi,

+0

Pensaci. Difficile. È possibile avere una classe come delegata, ma richiede pensiero. –

+0

@HotLicks Ho pensato a questo proposito, l'ho fatto con altre classi senza problemi? Puoi aiutare? –

+0

Il backtrace dovrebbe mostrarti il ​​ciclo in cui ti trovi. –

risposta

1

Un'idea ... Si può fare una Classe delegata che funge da intermediario tra il vero delegato e UITextView (perché tu farai probabilmente è necessario impostare il delegato dopo un po 'di tempo). Quindi questa nuova classe implementerà il protocollo delegato, ma avrà anche una proprietà per il proprio delegato, in modo che tu possa inoltrare textView: shouldChangeTextInRange: replacementText: e continui a modificare gli spazi nella tua classe middleMan.

+0

questo è quello che raccomando. Crea una classe helper che implementa 'UITextViewDelegate' e applica i comportamenti che desideri. Questa classe può avere il proprio protocollo se si desidera inviare messaggi al controller che gestisce la logica generale. Questo modello è utile in molti scenari, lo uso anche per 'UITableViewDataSource'. Finisci con implementazioni di protocollo belle, ordinate e riutilizzabili. – XJones

0

È possibile sottoscrivere qualsiasi numero di osservatori su un oggetto. Quindi è possibile iscriversi:

@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

Grazie, ma ho bisogno dei metodi 'should' che non possono essere osservati utilizzando il centro di notifica –

0

Ecco un esempio di come l'ho fatto con successo. Mi interessava solo impedire l'inserimento di alcuni caratteri, quindi implemento solo textView:shouldChangeTextInRange:replacementText: e poi passerò il resto.

#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 

Un grande 'Gotcha' che mi ha portato a questa domanda è stata stavo cercando di ignorare delegate tornare _externalDelegate ma che ha causato alcuni strani effetti collaterali (ci deve essere codice interno che dipende il delegato effettivo da restituire).

Problemi correlati