web-dev-qa-db-ja.com

クラスのインスタンスをObjective-Cの@protocolにキャストします

定義したプロトコルに準拠する場合としない場合があるオブジェクト(UIViewController)があります。

オブジェクトがプロトコルに準拠しているかどうかを判断し、メソッドを安全に呼び出すことができることを知っています。

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

ただし、XCodeは警告を表示します。

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

この警告を防ぐ正しい方法は何ですか? self.myViewControllerMyProtocolクラスとして。

95
Ford

これを行う正しい方法は次のとおりです。

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

UIViewController <MyProtocol> *型キャストは「vcはMyProtocolに準拠するUIViewControllerオブジェクト」に変換されますが、id <MyProtocol>を使用すると「vcはMyProtocolに準拠する未知のクラスのオブジェクト」に変換されます。

このように、コンパイラはvcに対して適切な型チェックを行います-UIViewControllerまたは<MyProtocol>のいずれかで宣言されていないメソッドが呼び出された場合のみ、コンパイラは警告を表示します。 idは、キャストされるオブジェクトのクラス/タイプがわからない場合にのみ使用してください。

163
Nick Forge

次のようにキャストできます。

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

これも少し私を投げました。 Objective-Cでは、プロトコルは型そのものではないため、id(またはNSObjectなどの他の型)を必要なプロトコルとともに指定する必要があります。

59
Andy