Swift クラスがプロトコルに準拠し、オプションの関数を実装しているかどうかを確認しますか? 質問する

Swift クラスがプロトコルに準拠し、オプションの関数を実装しているかどうかを確認しますか? 質問する

私は SpriteKit ゲームで使用するために、衝突の拘束が正しく設定されているかどうかを確認するヘルパー関数を Swift で作成しています。

GameScene がプロトコルを実装しSKPhysicsContactDeletegate、関数も含まれていることを確認したいと思いますdidBeginContact

Xcode のオートコンプリート機能を利用して記述した次のコードがあります。

    if GameScene(conformsToProtocol(SKPhysicsContactDelegate)) {
        if GameScene(respondsToSelector(didBeginContact(SKPhysicsContact))) {
            print("Self implements SKPhysicsContactDelegate and didBeginContact appears to be present")
        }
    }

Xcodeは私の について文句を言いconformsToProtocol

「引数ラベル '(_:)' は利用可能なオーバーロードと一致しません」

修正方法の提案はない。また、respondsToSelector次のように述べて、に反対している。

'(SKPhysicsContact).Type' (別名 'SKPhysicsContact.Type') 型の値を、期待される引数型 'SKPhysicsContact' に変換できません

GameScene がこのプロトコルに準拠し、この機能を実装しているかどうかを確認するにはどうすればよいですか?

編集: 回答に基づいた私のコードは次のとおりです:

if GameScene.self is SKPhysicsContactDelegate {
    print("Yes it's a delegate")
}

出力:Yes it's a delegate

let yy = (GameScene.self as? SKPhysicsContactDelegate)?.didBeginContact
print("yy is \(yy)")

出力:yy is nil

if (GameScene.self as? SKPhysicsContactDelegate)?.didBeginContact != nil {
    print("Yes it's a delegate and the function is there")
}

出力なし。

ベストアンサー1

まだ Objective-C で考えているなら、Swift を採用しましょう。

プロトコルが次のようになっていると仮定します。

@objc protocol SKPhysicsContactDelegate {
    optional func didBeginContact()
}

これを試して:

if let delegate = gameScene as? SKPhysicsContactDelegate {
    delegate.didBeginContact?()
}

あるいはワンライナー:

(gameScene as? SKPhysicsContactDelegate)?.didBeginContact?()

?呼び出しのメソッド名の後に注意してください。これは、そのメソッドがオプションであり、オブジェクトがそのメソッドを実装していない場合は呼び出されないためです。また、オブジェクトがプロトコルif letに準拠していない場合、ブランチは実行されません。SKPhysicsContactDeletegate


呼び出しなしでメソッドの存在を確認する

呼び出す前にメソッド自体の存在を確認するには、メソッド呼び出しを省略してそのメソッドへの参照を取得し、他の変数と同じように確認します。

if let method = (gameScene as? SKPhysicsContactDelegate)?.didBeginContact {
    print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact")
    // Call it later whenever you want
    method()
}

後で呼び出す必要がない場合は、次の点を確認してくださいnil:

if (gameScene as? SKPhysicsContactDelegate)?.didBeginContact != nil {
    print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact")
}

静的メソッドを確認する

メソッドのチェックでもoptional static同じアプローチが使用されますが、クラスのインスタンスではなくクラス オブジェクトが必要になります。

if (GameScene.self as? OptionalProtocol.Type)?.staticMethod != nil {
    print("gameScene conforms to OptionalProtocol and implements staticMethod")
}

GameScene.selfオブジェクト タイプを取得し、<protocol>.Typeプロトコル インスタンスではなくプロトコル クラスにキャストするための通知。


フルサンプル

遊び場の完全なサンプルを添付しました。Swift スクリプトまたはオンライン Swift コンパイラ:

import Foundation

@objc protocol OptionalProtocol {
    optional func instanceMethod()
    optional static func staticMethod()
}

class Nothing {}
class Something: OptionalProtocol {}
class Bar: NSObject, OptionalProtocol {
    func instanceMethod() {
        print("Instance method")
    }
}
class Foo: NSObject, OptionalProtocol {
    static func staticMethod() {
        print("Static method")
    }
}

// Cast instances to 'Any' and classes to 'AnyClass'
let nothing: Any = Nothing()
let nothingClass: AnyClass = Nothing.self
let something: Any = Something()
let somethingClass: AnyClass = Something.self
let bar: Any = Bar()
let barClass: AnyClass = Bar.self
let foo: Any = Foo()
let fooClass: AnyClass = Foo.self

nothing is OptionalProtocol // false
(nothing as? OptionalProtocol)?.instanceMethod != nil // false
(nothing as? OptionalProtocol)?.instanceMethod?() // Does nothing
(nothingClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(nothingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing

something is OptionalProtocol // true
(something as? OptionalProtocol)?.instanceMethod != nil // false
(something as? OptionalProtocol)?.instanceMethod?() // Does nothing
(somethingClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(somethingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing

bar is OptionalProtocol // true
(bar as? OptionalProtocol)?.instanceMethod != nil // true
(bar as? OptionalProtocol)?.instanceMethod?() // Prints 'Instance method'
(barClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(barClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing

foo is OptionalProtocol // true
(foo as? OptionalProtocol)?.instanceMethod != nil // false
(foo as? OptionalProtocol)?.instanceMethod?() // Does nothing
(fooClass as? OptionalProtocol.Type)?.staticMethod != nil // true
(fooClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Prints 'Static method'

おすすめ記事