Ale*_*ray 5 methods protocols class objective-c
我试图强制执行"正式" @protocol,但无法可靠地测试我的类/实例是否实际上实现协议的"必需"方法,而不是简单地"声明"它们符合协议.
我窘境的一个完整例子......
#import <Foundation/Foundation.h>
@protocol RequiredProtocol
@required
- (NSString*) mustImplement; @end
@interface Cog : NSObject <RequiredProtocol> @end
@implementation Cog @end
@interface Sprocket : NSObject @end
@implementation Sprocket
- (NSString*) mustImplement
{ return @"I conform, but ObjC doesn't care!"; } @end
int main(int argc, char *argv[]) {
Protocol *required = @protocol(RequiredProtocol);
SEL requiredSEL = @selector(mustImplement);
void (^testProtocolConformance)(NSObject*) = ^(NSObject *x){
NSLog(@"Protocol:%@\n"
"Does %@ class conform:%@ \n"
"Do instances conform:%@ \n"
"Required method's result:\"%@\"",
NSStringFromProtocol ( required ),
NSStringFromClass ( x.class ),
[x.class conformsToProtocol:required] ? @"YES" : @"NO",
[x conformsToProtocol:required] ? @"YES" : @"NO",
[x respondsToSelector:requiredSEL] ? [x mustImplement]
: nil );
};
testProtocolConformance ( Cog.new );
testProtocolConformance ( Sprocket.new );
}
Run Code Online (Sandbox Code Playgroud)
结果:
Protocol:RequiredProtocol
Does Cog class conform:YES
Do instances conform:YES
Required method's result:"(null)"
Protocol:RequiredProtocol
Does Sprocket class conform:NO
Do instances conform:NO
Required method's result:"I conform, but ObjC doesn't care!"
Run Code Online (Sandbox Code Playgroud)
为什么是它一个类,它是国家执行情况@protocol的方法(Sprocket)返回NO到conformsToProtocol?
为什么一个实际上并不符合规定,但是它确实会Cog回归YES?
什么是点正式协议,如果该声明是所有的需要假装一致性?
如果@selector没有MULTIPLE调用,你如何才能实际检查多个s的完整实现respondsToSelector?
@Josh Caswell ..没有diff这两个......我猜你的反应与NSObject我在此期间使用的类别实现了类似的效果......
@implementation NSObject (ProtocolConformance)
- (BOOL) implementsProtocol:(id)nameOrProtocol {
Protocol *p = [nameOrProtocol isKindOfClass:NSString.class]
? NSProtocolFromString(nameOrProtocol)
: nameOrProtocol; // Arg is string OR protocol
Class klass = self.class;
unsigned int outCount = 0;
struct objc_method_description *methods = NULL;
methods = protocol_copyMethodDescriptionList( p, YES, YES, &outCount);
for (unsigned int i = 0; i < outCount; ++i) {
SEL selector = methods[i].name;
if (![klass instancesRespondToSelector: selector]) {
if (methods) free(methods); methods = NULL; return NO;
}
}
if (methods) free(methods); methods = NULL; return YES;
}
@end
Run Code Online (Sandbox Code Playgroud)
符合协议只是一个"承诺",你可以不知道如果接收机conformsToProtocol:实际上实现了所有必需的方法.足以让您使用尖括号语法声明该类符合协议,并且conformsToProtocol:将返回yes:
讨论
如果一个类采用协议或从另一个采用它的类继承,则称该类符合协议.通过在接口声明后将它们放在尖括号内来采用协议.
完整来源:NSObject的conformsToProtocol : .
协议声明的优势在于,您可以在编译时知道类是否真正采用了所需的方法.如果没有,将发出警告.我建议不要依赖conformsToProtocol : ,而是使用内省代替.也就是说,验证类/对象是否通过调用instancesRespondToSelector实现方法:/respondsToSelector ::
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
- (BOOL)respondsToSelector:(SEL)aSelector;
Run Code Online (Sandbox Code Playgroud)