将一个类的实例转换为Objective-C中的@protocol

For*_*ord 96 protocols objective-c

我有一个对象(UIViewController),它可能符合也可能不符合我定义的协议.

我知道我可以确定对象是否符合协议,然后安全地调用该方法:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
    [self.myViewController protocolMethod]; // <-- warning here
}
Run Code Online (Sandbox Code Playgroud)

但是,XCode显示警告:

warning 'UIViewController' may not respond to '-protocolMethod'
Run Code Online (Sandbox Code Playgroud)

什么是防止此警告的正确方法?我似乎无法self.myViewController像一个MyProtocol班级一样.

Nic*_*rge 166

这样做的正确方法是:

if ([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
        UIViewController <MyProtocol> *vc = (UIViewController <MyProtocol> *) self.myViewController;
        [vc protocolMethod];
}
Run Code Online (Sandbox Code Playgroud)

UIViewController <MyProtocol> *型铸造转换为"VC是一个UIViewController对象符合MyProtocol",而使用id <MyProtocol>转换为"VC是符合MyProtocol未知类的对象".

通过这种方式,编译器将为您提供正确的类型检查vc- 如果任何方法未在任何方法上声明UIViewController或被<MyProtocol>调用,编译器将仅向您发出警告.id只有在您不知道正在投射的对象的类/类型时才应该在这种情况下使用.

  • 使用协议时,你真的不应该关心对象类型 - 协议的全部意义在于任何对象类型都可以采用它并且无需转换为特定对象即可使用.因此,我建议使用@andy的答案,无论你在哪里投射到协议而不是上面的 - "id <MyProtocol> p =(id <MyProtocol>)self.myViewController;`这个答案和@andys都是正确的,但他的_更正确. (2认同)
  • @Answerbot您的评论不正确,并且错过了我在答案的最后一段中提出的观点。您可能会或可能不会在乎对象类型,这取决于情况。如果要在我的答案示例中将在“ UIViewController”上声明的消息发送到“ vc”,并且声明为“ id &lt;MyProtocol&gt;”,会发生什么? (2认同)

And*_*ndy 59

你可以这样投:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
    id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
    [p protocolMethod];
}
Run Code Online (Sandbox Code Playgroud)

这也让我感到有些失望.在Objective-C中,协议本身不是类型,因此您需要指定id(或某些其他类型,例如NSObject)以及您想要的协议.