self
может быть использован в качестве метода класса в качестве экземпляра класса полиморфного.
поэтому метод класса new
может быть реализован следующим образом:
+ (id)new
{
return [[self alloc] init];
}
и вернет правильный тип для экземпляра класса, который обменивался сообщения:
франко:
NSArray * a = [NSArray new]; // << a is an NSArray
ex b:
NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray
см. Примечание ниже.
Итак, на самом деле вы сталкиваетесь с тем, что в протоколе есть только методы экземпляра, и методы (класса) self для отображения методов экземпляра в протоколе.
Что касается дизайна ... ну, скажем так, я бы не написал это так. Синглтон был бы яснее и правильнее, но мне даже не нравятся одиночки, поэтому я бы не пошел по этому пути.
Предупреждения производится, так как класса экземпляр (что передается) не принимает @protocol
заданного параметром delegate
. Экземпляр Class
не является экземпляром класса. Объявление протокола действительно относится к экземплярам класса. Например, если вы принимаете NSLocking
, компилятор ожидает, что вы также будете применять методы класса для каждого метода экземпляра, объявленного в протоколе? Ответ: Никогда. Реализация, с которой вы имеете дело, - это ИМО, один из тех случаев, когда это неправильное использование языка, но это происходит.
Для того, чтобы уточнить терминологию:
"Class
экземпляр" является self
в методе класса:
+ (void)foo { self; }
"Экземпляр класса" находится в метод экземпляра self
:
- (void)foo { self; }
На практике -[NSObject conformsToProtocol:]
является +[NSObject conformsToProtocol:]
и +[NSObject class]
всего лишь возвращает self
, поэтому при выполнении ошибок нет ошибок.
По-прежнему неясно, почему я получаю предупреждение, если код соответствует указанным вами критериям.
Критериями я описал относится к исполнения, но она отличается от семантики языка - таким образом, компилятор абсолютно правильно на этом.
Для разрешения этой проблемы: Там нет никакого способа, чтобы сообщить компилятору «Мой экземпляр класса Соответствует протоколу», поскольку заявление о принятии относится к экземплярам класса.
У вас есть два основных варианта:
Чистый, правильный подход: использовать экземпляр класса и реализации протокола, как определено.
или напечатанный экземпляр класса к протоколу:
ID Делегат = (ID) самостоятельно; fbSession = [FBSession sessionForApplication: SHKFacebookKey getSessionProxy: SHKFacebookSessionProxyURL делегат: delegate];
Если вы выбираете # 2, это может помочь определить методы экземпляра протокола использовать методы класса, например, так:
+ (void)protocolMethod { /* do stuff */ }
- (void)protocolMethod { [self.class protocolMethod]; }
, что также означает, вам не нужны экземпляры. Это поможет, потому что оно добавит предупреждения, если протокол изменится. Эти предупреждения будут выходить за рамки методов класса, когда вы будете следовать этому соглашению.
Для снижения уровня шума, вы можете также рассмотреть вопрос о создании какой-то способ, чтобы уменьшить приведение типа в одном месте:
+ (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return (id<SomeProtocol>)self;
}
- (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return [[self class] sharedSomeProtocolDelegate];
}
, то вы можете просто написать:
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:[self sharedSomeProtocolDelegate]];
(обратите внимание, что реализации эти типы на самом деле являются классовыми кластерами, и вы увидите что-то другое в отладчике или напечатано)
Ваше изменение дает понять. Протокол содержит только методы экземпляра, и, кстати, ни один из них не ссылается на приемник. Я все еще не понимаю, почему я получаю предупреждение, если код соответствует указанным вами критериям. – Jim
@ Jim подробно добавлено – justin