È semplicemente lo stesso concetto ereditarietà per le classi. Se un protocollo adotta un altro protocollo, "eredita" i metodi dichiarati di questo protocollo adottato.
Il protocollo NSObject
dichiara in particolare metodi come respondsToSelector:
. Quindi questo è particolarmente utile se si dichiara un @protocol
che ha metodi @optional
, perché quando si chiameranno i metodi su oggetti conformi a questo protocollo, sarà necessario verificare se l'oggetto risponde al metodo prima di chiamarlo se questo metodo è facoltativo.
@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
Lei sarà solo in grado di chiamare respondsToSelector
su myDelegate se myDelegate
è dichiarato come un tipo che implementa respondsToSelector
(in caso contrario si avrà alcuni avvisi). Ecco perché il protocollo <SomeProtocol>
deve adottare se stesso il protocollo <NSObject>
, che a sua volta dichiara questo metodo.
Si può pensare di id<SomeProtocol>
come "qualsiasi oggetto, di qualsiasi tipo (id
), si deve solo implementare i metodi dichiarati nel SomeProtocol
, compresi i metodi dichiarati nel protocollo genitore NSObject
. Così può essere un oggetto di qualsiasi digitare ma perché SomeProtocol
adotta il protocollo NSObject
in sé, è garantito che si è permesso di chiamare respondsToSelector
su questo oggetto, che consente di controllare se l'oggetto implementa un dato metodo prima di chiamare se è facoltativa.
Si noti inoltre che non è possibile effettuare SomeProtocol
adotta il protocollo NSObject
e dichiarare invece la variabile come id<SomeProtocol,NSObject> myDelegate
in modo che sia ancora possibile chiamare respondsToSelector:
. Ma se lo fai che sarà necessario dichiarare tutte le variabili in questo modo in tutto il mondo si utilizza questo protocollo ... Quindi questo è molto più logico per rendere SomeProtocol
adottare direttamente il protocollo NSObject
;)
Si noti che il fatto che il protocollo originale sia conforme a 'NSObject' non è strettamente necessario per evitare avvisi. Invece di usare 'id myDelegate', usa' NSObject * myDelegate'. –
Sì, anche questa può essere una soluzione. Ma inserisce una dipendenza dai tipi (anche se è improbabile che ciò accada, alcuni potrebbero usare NSProxy o qualsiasi altra cosa: sono d'accordo che questo è raro e raro, ma comunque), quindi in qualche modo viola il principio di obiezione del OOP. Se non vi è alcun motivo per costringere l'utente a utilizzare una classe che eredita esplicitamente NSObject, ma invece è solo necessario implementare alcuni metodi, perché forzarlo ...l'approccio corretto è quindi quello di utilizzare il protocollo 'NSObject' e il tipo' id ', non il tipo NSObject, per mantenere collegamenti deboli tra i tipi ed evitare una tipizzazione forte. –
AliSoftware