swift - 类型 'X' 的值没有成员 'y' - 协议(protocol)中的可选函数

标签 swift swift-protocols

我正在尝试更好地理解 Swift 中的协议(protocol)。特别是可选的协议(protocol)方法。我认为这个问题可能与我的协议(protocol)在不同的文件中定义/使用有关,但如果你将以下内容放在 Playground 上,你会遇到同样的问题:

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 上定义的协议(protocol)。代码完成找到它,但编译器不允许它通过。

我不确定我的?? true 部分将起作用,但我希望它成为默认值,以防未定义该方法。

我如何让它工作?

最佳答案

您的 NSObject 符合 MyProtocol,但是因为它没有实现可选的协议(protocol)方法,所以编译器知道它没有 Selector shouldJump:

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

解决这个问题的一种方法是在扩展中实现协议(protocol)方法,以便对象执行该选择器:

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

如果您不想在扩展中实现可选方法,您必须将 NSObject 转换为 MyProtocol 并验证它是否响应可选的 选择器:

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 letguard 来验证 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")
        }
    }
}

关于swift - 类型 'X' 的值没有成员 'y' - 协议(protocol)中的可选函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35591784/

相关文章:

swift - 从继承的 UIView 类获取 ViewController

ios - 如何在 Swift 中使用关联类型测试协议(protocol)的一致性?

swift - Swift 中的类内部协议(protocol)

arrays - 从供应商函数填充数组的 Swifty 方法

objective-c - 如何从这个解析结果中单独获取日期和标题和描述

swift - Swift 中的动态调度和协议(protocol)

swift - 非'@objc'方法不满足'@objc'协议(protocol)的可选要求

ios - 实例方法几乎匹配可选需求

swift - 如何折叠结构数组?

swift - 在 Swift 的类扩展函数中使用 'self'