2012-06-26 24 views
5

Tôi có một lớp con của một UITextView và tôi muốn làm cho nó là đại biểu của chính nó. Để tôi có thể ghi đè phương thức textView:shouldChangeTextInRange:replacementText: và ngăn không gian liên tiếp được nhập.UITextView là đại biểu của riêng có nghĩa là vòng lặp vô hạn

Trong [SATextView awakeFromNib] (SATextView là lớp con của UITextView), tôi làm [self setDelegate:self];. Khi tôi bấm vào textview để bắt đầu chỉnh sửa tất cả mọi thứ đóng băng và cuối cùng dừng lại, và backtrace cho thấy rằng đã có một vòng lặp vô hạn.

Không quan trọng nếu tôi triển khai tất cả các phương thức đại biểu, chỉ một hoặc không có phương pháp nào. Cũng không quan trọng nếu những phương pháp đó trống.

Tại sao điều này gây ra vòng lặp vô hạn? Nó chỉ dường như xảy ra nếu với UITextView (các đối tượng khác bạn có thể phân lớp và thiết lập các đại biểu để tự, và nó sẽ không có vấn đề này). Và làm thế nào tôi có thể ngăn chặn nó? Hoặc có cách nào tốt hơn để lớp con này không thể có các khoảng trắng liên tiếp,

+0

Hãy nghĩ về điều đó. Cứng. Có thể có một lớp là đại diện riêng của nó, nhưng nó đòi hỏi sự suy nghĩ. –

+0

@HotLicks Tôi có mặc dù về nó, tôi đã thực hiện nó với các lớp khác mà không có vấn đề? Bạn có thể giúp? –

+0

Backtrace sẽ hiển thị cho bạn vòng lặp mà bạn đang sử dụng. –

Trả lời

1

Ý tưởng ... Bạn có thể tạo Lớp đại biểu đóng vai trò trung gian giữa đại biểu thực và UITextView (vì bạn sẽ có thể cần phải thiết lập các đại biểu sau một thời gian). Vì vậy, lớp mới này sẽ thực hiện giao thức đại biểu, nhưng nó cũng sẽ có một thuộc tính cho đại biểu riêng của nó, để bạn có thể chuyển tiếp textView: shouldChangeTextInRange: replaceText :, và vẫn làm công việc chỉnh sửa các không gian trong lớp trung gian của bạn.

+0

đây là những gì tôi đề nghị. Tạo một lớp trợ giúp triển khai thực hiện 'UITextViewDelegate' và thực thi các hành vi mà bạn muốn. Lớp này có thể có giao thức riêng của nó nếu muốn gửi tin nhắn tới bộ điều khiển quản lý logic tổng thể. Mẫu này rất hữu ích trong nhiều trường hợp, tôi cũng sử dụng nó cho 'UITableViewDataSource'. Bạn kết thúc với việc triển khai giao thức đẹp, gọn gàng, có thể tái sử dụng. – XJones

0

Có thể đăng ký bất kỳ số người quan sát nào với một đối tượng. Vì vậy, có thể tự đăng ký:

@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

Cảm ơn, nhưng tôi cần các phương thức 'nên' không thể quan sát được bằng cách sử dụng trung tâm thông báo –

0

Đây là ví dụ về cách tôi đã thực hiện thành công việc này. Tôi chỉ quan tâm đến việc ngăn chặn các ký tự nhất định không được nhập vào nên tôi chỉ thực hiện textView:shouldChangeTextInRange:replacementText: và sau đó chuyển phần còn lại vào.

#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 

Một lớn 'Gotcha' mà dẫn tôi đến câu hỏi này đã được tôi đã cố gắng để ghi đè delegate trở _externalDelegate nhưng điều đó gây ra một số tác dụng phụ kỳ lạ (phải có mã nội bộ mà phụ thuộc vào các đại biểu thực tế để được trả lại).

Các vấn đề liên quan