Objective-C class_conformsToProtocol() ошибка?
Я столкнулся с каким-то странным поведением в приложении iPhone Objective-C.
Я использую некоторый код для проверки объекта:
if (!class_conformsToProtocol([someVar someFunctionThatReturnsAClass], @protocol(MyProtocol)))
[NSException raise:@"Invalid Argument" format:@"The variables returned by 'someFunctionThatReturnsAClass' Must conform to the 'myProtocol' protocol in this case."];
Как ни странно, когда у меня есть класс, который выглядит так:
@interface BaseClass : NSObject<MyProtocol>
...
@end
@interface SubClass : BaseClass
...
@end
И когда я вызываю этот фрагмент: class_conformsToProtocol([SubClass class], @protocol(MyProtocol))
, он возвращает NO
.
Кроме того, этот код не работает:
class_conformsToProtocol([NSString class], @protocol(NSObject)); // also returns NO
Пока этот код возвращает YES
:
[NSString conformsToProtocol:@protocol(NSObject)];
Есть ли что-нибудь, что мне не хватает в документах?
Или это какая-то ошибка? (Я на iOS 4.2, если это имеет значение).
Ответы
Ответ 1
Используйте NSObject
conformsToProtocol:
.
Здесь эксперимент, который я пробовал:
@protocol MyProtocol
- (void) doSomething;
@end
@interface MyClass : NSObject<MyProtocol>
{
}
@end
@implementation MyClass
- (void) doSomething {
}
@end
@interface MyOtherClass : MyClass
{
}
@end
@implementation MyOtherClass
- (void) doSomething {
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyClass *obj_one = [MyClass new];
BOOL one_conforms = [obj_one conformsToProtocol:@protocol(MyProtocol)];
MyOtherClass *obj_two = [MyOtherClass new];
BOOL two_conforms = [obj_two conformsToProtocol:@protocol(MyProtocol)];
NSLog(@"obj_one conformsToProtocol: %d", one_conforms);
NSLog(@"obj_two conformsToProtocol: %d", two_conforms);
[pool drain];
return 0;
}
Вывод:
obj_one conformsToProtocol: 1
obj_two conformsToProtocol: 1
В то время как:
MyOtherClass *obj_two = [MyOtherClass new];
BOOL conforms_two = class_conformsToProtocol([obj_two class], @protocol(MyProtocol));
NSLog(@"obj_two conformsToProtocol: %d", conforms_two);
Вывод:
obj_two conformsToProtocol: 0
Вердикт:
Это ошибка с class_conformsToProtocol
, используйте метод conformsToProtocol:
NSObject
В отличие от class_conformsToProtocol
, метод NSObject
conformsToProtocol:
также проверяет суперклассы.
Ответ 2
Если там ошибка, это в документации.
Согласно источнику, class_conformsToProtocol()
использует class_copyProtocolList()
, а затем проверяет каждый результирующий протокол на параметр. class_copyProtocolList()
документируется как только возвращаемые протоколы, которые данный класс принимает, но не протоколы, принятые суперклассами. class_conformsToProtocol()
поэтому проверяет, только если данный класс принимает протокол, а не его суперклассы.
Ошибка в документации: class_conformsToProtocol()
не указывает это поведение. Однако в документации указано, что вы вообще не должны использовать эту функцию, вместо этого вместо этого используйте NSObject
conformsToProtocol:
.