2010-02-13 2 views
4

Я создал класс, который обертывает UITextView и добавляет некоторые элементы ui. Я хочу, чтобы API нового класса был идентичен с UITextView, поэтому я использую пересылку сообщений (список ниже) для передачи сообщений между обернутым текстовым представлением и делегатом.Избегание предупреждений компилятора при выполнении пересылки сообщений

Раздражает то, что компилятор выдает предупреждения для вызовов методов в экземплярах моего класса переадресации. Например, ошибка будет генерироваться для следующей строки:

[aMyTextView setContentOffset:CGPointZero animated:YES]; 

Поэтому я вынужден объявить и создавать «вручную переадресации» реализаций этих методов, побеждает вся цель использования пересылки сообщений.

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated 
{ 
    [_textView setContentOffset:contentOffset animated:animated]; 
} 

Я знаю, что обычный способ обойти это, чтобы использовать один из performSelector: методов, но это) громоздки, когда некоторые аргументы не являются NSObjects (хотя Erica Sadun's extensions большая помощь), б) снова, полностью противоречит намерению создать прозрачную оболочку.

(подклассов UITextView также может быть и речи, потому что мне нужно вставить взгляды ниже точки зрения текста.)

Есть ли способ обойти это?

Список всех соответствующих частей класса:

@interface MyTextField : UIView<UITextViewDelegate> 
{ 
    UIImageView*      _border; 
    UITextView*       _textView; 
    UIButton*       _clearButton; 
    NSObject<UITextViewDelegate>*  _delegate; 
} 

@implementation MWTextField 
. . . 
// Forwards messages in both directions (textView <--> delegate) 
#pragma mark Message forwarding 

// Protocol messages will only be sent if respondsToSelector: returns YES 
- (BOOL)respondsToSelector:(SEL)aSelector 
{ 
    if ([_delegate respondsToSelector:aSelector]) 
     return YES; 
    else 
     return [super respondsToSelector:aSelector]; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 
{ 
    // First, try to find it in the UITextView 
    if ([_textView respondsToSelector:selector]) 
    { 
     return [_textView methodSignatureForSelector:selector]; 
    } 
    // Then try the delegate 
    else if ([_delegate respondsToSelector:selector]) 
    { 
     return [_delegate methodSignatureForSelector:selector]; 
    } 
    else 
    { 
     return [super methodSignatureForSelector: selector]; 
    } 
} 

- (void)forwardInvocation:(NSInvocation *)invocation 
{ 
    SEL aSelector = [invocation selector]; 

    if ([_textView respondsToSelector:aSelector]) 
    { 
     [invocation invokeWithTarget:_textView]; 
    } 
    else if ([_delegate respondsToSelector:aSelector]) 
    { 
     [invocation invokeWithTarget:_delegate]; 
    } 
    else 
    { 
     [self doesNotRecognizeSelector:aSelector]; 
    } 
} 
. . . 
@end 

ответ

4

Объявите категорию, которая предоставляет объявления методов из методов вы экспедиторские:

@interface MyTextField (ImGonnaLetYouFinishButFirstImForwardingThese) 
... methods you want to forward here ... 
@end 

Нет необходимости обеспечить @implementation.

Обратите внимание, что это довольно нетипичный рисунок. Не очень, очень. Не должно быть причин, по которым вы не можете подкласса. Вы говорите: Подкласс UITextView тоже не может быть и речи, потому что мне нужно вставить виды под текстовым видом, но это не так.


Если я подкласс UITextField, все, что я могу сделать с другими видами, чтобы добавить их в качестве подвидов, что означает, что они будут на верхней части текстового поля. Думаю, я мог бы изменить drawRect: ... Это то, что вы бы предложили? Или что у вас есть до твоего рукава?

Если вам нужна группа, создайте подкласс UIView, который соответствующим образом управляет различными subview, без необходимости пересылки. Тогда вы можете заказать мнения, как вам нравится.

Экспедирование используется крайне редко. Вниз этот путь - безумие. По-настоящему кажется, что ваш дизайн немного в сорняках, но информации недостаточно, чтобы действительно сказать что-то более конкретное.

+0

Ваше решение: приятно, но было бы еще лучше не декларировать методы, а просто пересылать их, какими бы они ни были. Подкласс: я хочу сгруппировать фактическое текстовое поле с некоторыми элементами, по крайней мере одно из которых должно появиться * под * текстовым полем. Если я подклассифицирую UITextField, все, что я могу сделать с другими представлениями, это добавить их как subviews, что означает, что они будут поверх текстового поля. Думаю, я мог бы изменить drawRect: ... Это то, что вы предложили бы? Или у тебя там рукава? – Felixyz

+0

Но как вы могли исправить пересылку без предупреждения и предупреждения, когда вы имеете в виду? Экспедирование чрезвычайно динамично. Что касается подклассификации, вы можете сделать что-либо в своем подклассе, который вы делаете в своем пользовательском классе. – bbum

+0

Вы правы, конечно. Если я сделаю эти предупреждения, то все остальные тоже уйдут, что не будет хорошо. Таким образом, ваше решение для протокола кажется лучшим. Подкласс не смог бы поставить представление под (в терминах порядка рисования) сам, потому что это представление было бы subview и как таковое всегда располагалось над родительским представлением. Правильно? – Felixyz

0

Простым решением является использование динамической типизации и объявление aMyTextView как id, предупреждения будут уходить.

+0

Исправьте, но рискует выйти из строя во время выполнения, если отправлен неправильный метод. Лично мне все равно хотелось бы знать, почему OP считает, что подклассы невозможны. :) – bbum

Смежные вопросы