Это просто та же концепция, что и наследование для классов.Если протокол принимает другой протокол, он «наследует» объявленные методы этого принятого протокола.
Протокол NSObject
особенно объявляет такие методы, как respondsToSelector:
.Так что это особенно полезно, если вы объявляете @protocol
, который имеет @optional
методы, потому что когда вы будете затем вызывать методы для объектов, соответствующих этому протоколу, вам нужно будет проверить, отвечает ли объект на метод, прежде чем вызывать его, если этот методне является обязательным.
@protocol SomeProtocol <NSObject>
-(void)requiredMethod;
@optional
-(void)optionalMethod;
@end
@interface SomeObject : NSObject
-(void)testMyDelegate;
@property(nonatomic, assign) id<SomeProtocol> myDelegate;
@end
@implementation SomeObject
@synthesize myDelegate
-(void)testMyDelegate {
// Here you can call requiredMethod without any checking because it is a required (non-optional) method
[self.myDelegate requiredMethod];
// But as "optionalMethod" is @optional, you have to check if myDelegate implements this method before calling it!
if ([myDelegate respondsToSelector:@selector(optionalMethod)]) {
// And only call it if it is implemented by the receiver
[myDelegate optionalMethod];
}
}
@end
Вы можете вызывать respondsToSelector
на myDelegate, только если myDelegate
объявлен как тип, который реализует respondsToSelector
(в противном случае у вас будут некоторые предупреждения).Вот почему протокол <SomeProtocol>
должен принять сам протокол <NSObject>
, который сам объявляет этот метод.
Вы можете думать о id<SomeProtocol>
как о «любом объекте, независимо от его типа (id
),ему просто нужно реализовать методы, объявленные в SomeProtocol
, включая методы, объявленные в родительском протоколе NSObject
. Таким образом, это может быть объект любого типа, но , потому что SomeProtocol
принимает сам протокол NSObject
,гарантируется, что вам разрешено вызывать respondsToSelector
для этого объекта, что позволяет вам проверить, реализует ли объект данный метод, прежде чем вызывать его, если это необязательно .
Обратите внимание, что вы также не можете заставить SomeProtocol
принять протокол NSObject
и вместо этого объявить вашу переменную как id<SomeProtocol,NSObject> myDelegate
, чтобы вы все равно могли вызвать respondsToSelector:
. Но если вы сделаете это, вам нужно будет объявить все свои переменные таким образомвезде, где вы используете этот протокол ... Так что гораздо логичнее заставить SomeProtocol
напрямую принимать протокол NSObject
;)