как расширить протокол для делегата в задаче C, а затем создать подкласс для объекта, требующего соответствующего делегата - PullRequest
30 голосов
/ 18 мая 2010

Я хочу создать подкласс UITextView и отправить новое сообщение делегату. Итак, я хочу расширить протокол делегата. Какой правильный способ сделать это?

Я начал с этого:

интерфейс:

#import <Foundation/Foundation.h>

@class MySubClass;

@protocol MySubClassDelegate <UITextViewDelegate>
- (void) MySubClassMessage: (MySubClass *) subclass;
@end


@interface MySubClass : UITextView {
}

@end

реализация:

#import "MySubClass.h"


@implementation MySubClass

- (void) SomeMethod; { 
    if ([self.delegate respondsToSelector: @selector (MySubClassMessage:)]) { 
        [self.delegate MySubClassMessage: self];
    }
}

@end

однако с этим я получаю предупреждение: '-MySubClassMessage:' not found in protocol(s).

У меня был один способ работы, где я создал свой собственный ivar для хранения делегата, а затем также сохранил делегат, используя [super setDelegate], но это казалось неправильным. возможно это не так.

Я знаю, что могу просто передать id и обойтись, но моя цель - убедиться, что компилятор проверяет, что любой делегат, предоставленный MySubClass, соответствует протоколу MySubClassDelegate.

Для дальнейшего ясновидения:

@interface MySubClassTester : NSObject {

}

@implementation MySubClassTester

- (void) one { 
    MySubClass *subclass = [[MySubClass alloc] init];
    subclass.delegate = self;
}

@end

выдаст предупреждение: class 'MySubClassTester' does not implement the 'UITextViewDelegate' protocol

Я хочу, чтобы вместо этого было выдано предупреждение о том, что протокол MySubClassDelegate не реализован.

Ответы [ 4 ]

24 голосов
/ 18 мая 2010

UITextView определяет delegate как

@property(nonatomic, assign) id<UITextViewDelegate> delegate

означает, что он соответствует UITextViewDelegate, и именно это проверяет компилятор. Если вы хотите использовать новый протокол, вам нужно переопределить delegate для соответствия вашему протоколу:

@interface MySubClass : UITextView {
}
@property(nonatomic, assign) id<MySubClassDelegate> delegate   
@end

Компилятор не должен выдавать больше предупреждений.

[Обновление по fess]

... При этом компилятор предупредит, что средства доступа должны быть реализованы ... [Я реализовал это:]

-(void) setDelegate:(id<MySubClassDelegate>) delegate {
[super setDelegate: delegate];
}
- (id) delegate {
return [super delegate];
}

"

[Мое обновление]

Я считаю, что это должно сработать, если вы сделаете объявление @dynamic вместо переопределения метода, так как реализация уже существует:

@dynamic delegate;
7 голосов
/ 14 сентября 2012

Для всех, кто еще заинтересован, это может быть сделано довольно просто, как это (для примера я подкласс UIScrollView):

@protocol MySubclassProtocol <UIScrollViewDelegate>
@required
-(void)myProtocolMethod;
@end

@interface MySubClass : UIScrollView

@property (nonatomic, weak) id <MySubclassProtocol> delegate;

Самая важная деталь здесь - это часть между <> после названия вашего протокола, которая, проще говоря, сигнализирует о расширении этого протокола. В вашей реализации все, что вам нужно сделать, это:

@synthesize delegate;

И все готово.

2 голосов
/ 17 января 2014

Вам нужно расширить супер-протокол:

@protocol MYClassProtocol <SuperClassProtocol>
-(void)foo;
@end

после этого НЕ (!!!) создайте @ свойство для делегата, в противном случае вы переопределяете исходный объект делегата, но просто переопределяете метод:

- (id<MYClassProtocol>)delegate
{
    return (id<MYClassProtocol>)[super delegate];
}

теперь вы можете использовать делегата классическим способом:

[self.delegate foo];
[self.delegate someSuperClassDelegateMethod];
1 голос
/ 18 мая 2010

Учитывая, что MySubClassMessage: не является обязательным, вы должны иметь возможность просто сделать простое:

- (void) SomeMethod { 
  SEL delegateSelector = @selector(MySubClassMessage:);
  if ([self.delegate respondsToSelector:delegateSelector]) { 
    [self.delegate performSelector:delegateSelector withObject:self];
  }
}

Компилятор должен по-прежнему проверять, что реализующий класс соответствует вашему протоколу (или хотя бы утверждать, что в заголовке), и вы не получите ошибку, которую вы описали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...