Избегать предупреждений компилятора при выполнении пересылки сообщений - PullRequest
4 голосов
/ 13 февраля 2010

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

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

[aMyTextView setContentOffset:CGPointZero animated:YES];

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

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

Я знаю, что обычный способ обойти это - использовать один из performSelector: методов, но это) громоздко, когда некоторые аргументы не являются объектами NSO (хотя расширения Эрики Садун очень помогают ), б) опять же, полностью противоречит намерению создать прозрачную обертку.

(Подкласс 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

Ответы [ 2 ]

4 голосов
/ 14 февраля 2010

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

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

Не нужно указывать реализацию @.

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

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

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

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

0 голосов
/ 14 февраля 2010

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

...