6

Swift のプロトコルをよりよく理解しようとしています。具体的には、オプションのプロトコル メソッドです。この問題は、プロトコルが別のファイルで定義/使用されていることに関係している可能性があると考えましたが、プレイグラウンドに次のものを配置すると、同じ問題が発生します。

import Foundation

@objc protocol MyProtocol {
    optional func shouldJump() -> Bool
}

extension NSObject : MyProtocol {}

class Test {
    func testJump() {
        let object = NSObject()
        let jump = object.shouldJump?() ?? true

        print("should jump: \(jump)")
    }
}

let t = Test()
t.testJump()

エラーメッセージは次のとおりです。

error: value of type 'NSObject' has no member 'shouldJump'
            let jump = object.shouldJump?() ?? true
                       ^~~~~~ ~~~~~~~~~~

何らかの理由で、プロトコルが NSObject で定義されていることを受け入れません。コード補完はそれを見つけますが、コンパイラはそれを通過させません。

私の?? true部分が機能するかどうかはわかりませんが、メソッドが定義されていない場合に備えて、それをデフォルト値にしたいと考えています。

これを機能させるにはどうすればよいですか?

4

3 に答える 3

2

あなたは にNSObject準拠しMyProtocolていますが、オプションのプロトコルメソッドを実装していないため、コンパイラは次のものを持っていないことを認識していますSelector shouldJump:

let object = NSObject()
object.conformsToProtocol(MyProtocol) // true
object.respondsToSelector("shouldJump") // false

これを解決する 1 つの方法は、オブジェクトがそのセレクターを実行するために拡張機能にプロトコル メソッドを実装することです。

extension NSObject : MyProtocol {
    func shouldJump() -> Bool {
        // some logic here
        return true
    }
}

class Test {
    func testJump() {
        let object = NSObject()

        let jump = object.shouldJump()

        print("should jump: \(jump)")
    }
}

let t = Test()
t.testJump() // works

オプションのメソッドを拡張機能に実装したくない場合は、NSObjectasをキャストMyProtocolして、オプションに応答することを確認する必要がありますSelector

class Test {
    func testJump() {
        let object = NSObject()

        let obj = object as MyProtocol

        if object.respondsToSelector("shouldJump")  {
            let jump = obj.shouldJump?()

            print("should jump: \(jump)")
        } else {
            print("nope")
        }


    }
}

respondsToSelectorこのステップをスキップしてif letorを使用して、非 nilguardが返されることを確認することもできます。shouldJump()

class Test {
    func testJump() {
        let object = NSObject()

        guard let obj: MyProtocol = object else {
            return // object does not conform to MyProtocol
        }

        if let jump = obj.shouldJump?() { // if shouldJump() returns non-nil
            print("should jump: \(jump)")
        } else {
            print("nope")
        }
    }
}
于 2016-02-24T02:21:18.770 に答える