在 Objective-C 中将类的实例强制转换为@协议

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

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

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

然而,XCode 显示了一个警告:

warning 'UIViewController' may not respond to '-protocolMethod'

防止这种警告的正确方法是什么? 我似乎不能将 self.myViewController转换为 MyProtocol类。

37218 次浏览

You can cast it like this:

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

This threw me for a bit, too. In Objective-C, the protocol isn't the type itself, so you need to specify id (or some other type, such as NSObject) along with the protocol that you want.

The correct way to do this is to do:

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

The UIViewController <MyProtocol> * type-cast translates to "vc is a UIViewController object that conforms to MyProtocol", whereas using id <MyProtocol> translates to "vc is an object of an unknown class that conforms to MyProtocol".

This way the compiler will give you proper type checking on vc - the compiler will only give you a warning if any method that's not declared on either UIViewController or <MyProtocol> is called. id should only be used in the situation if you don't know the class/type of the object being cast.