检查对象是否符合Objective-C中的两个单独协议

时间:2011-01-10 11:44:47

标签: objective-c cocoa cocoa-touch protocols compile-time

在Objective-C中,当您声明一个实例变量时,您可以检查它是否符合编译时分配的协议,如下所示:

id <MyProtocol> variable;

是否可以在编译时检查分配给变量的对象是否符合两个单独的协议?如:

id <MyProtocol, MyOtherProtocol> variable;

我知道我可以使用conformsToProtocol:respondsToSelector等进行运行时检查(我在实际使用对象之前做的是为了增加安全性),我可以编写自己的setter方法来执行检查,但我想在编译时知道。

3 个答案:

答案 0 :(得分:53)

是的,这种语法是正确的。

检查对象是否符合协议的正确方法是:

if ([myObj conformsToProtocol:@protocol(MyProtocol)]) {
  //conformance!
}

请注意,这既适用于实例方法,也适用于类方法。

如果由于某些奇怪的原因您无法使用conformsToProtocol:,您可以下拉到运行时级别:

#import <objc/runtime.h>

Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
  //conformance!
}

答案 1 :(得分:12)

我认为最好是使用自己的代码:

id <MyProtocol, MyOtherProtocol> variable;

在调用方法之前,检查变量是否响应您要调用的内容:

if ([variable respondsToSelector:@selector(aMethod:)]) {
    [variable aMethod:nil];
}

由于Objective-C是一种动态语言,只是声明变量协议无法保证它符合协议。它会在你构建时产生警告。

答案 2 :(得分:3)

您无法始终在编译时检查协议一致性,因为(非限定)类型id的对象始终是编译器角度的有效对象。例如,

id<P1> p1;
id<P2> p2;
id p0;

// compiler warning: assigning to 'id<P1>' from incompatible type 'id<P2>'
p1 = p2;

// no compiler warning
p0 = p2;
p1 = p0;

话虽这么说,<P1, P2>会给你警告,以防对象不符合 if 这两个协议,这些协议可以在编译时知道:

id<P1> p1;
id<P2> p2;
id<P1, P2> p12;
id<P1, P2> q12;
id p0;

p12 = p1; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P1>'
p12 = p2; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P2>'
p12 = q12; // no compiler warning

// no compiler warning
p0 = p1;
p12 = p0;