'X' 类型的值没有成员 'y' - 协议中的可选函数
Value of type 'X' has no member 'y' - optional func in protocol
我正在尝试更好地理解 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
部分是否有效,但我希望它是默认值,以防未定义该方法。
如何让它工作?
我认为这是因为编译器知道 NSObject 没有 shouldJump
方法,所以调用 object.shouldJump?()
没有意义。您可以将 object
转换为您的协议:
let jump = (object as MyProtocol).shouldJump?() ?? true
Swift 是一种类型安全的语言。为了能够使用 shouldJump?()
,您首先必须有一个符合 MyProtocol
的对象。在这种情况下,您可以简单地转换类型:
let jump = (object as MyProtocol).shouldJump?() ?? true
您也可以将其存储在变量中:
let jumper = object as MyProtocol
let jump = jumper?.shouldJump() ?? true
你的 NSObject
符合 MyProtocol
,但是因为它没有实现可选的协议方法,所以编译器知道它没有 Selector
shouldJump
:
let object = NSObject()
object.conformsToProtocol(MyProtocol) // true
object.respondsToSelector("shouldJump") // false
解决这个问题的一种方法是在扩展中实现协议方法,以便对象执行该选择器:
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
并验证它是否响应可选 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 let
或 guard
来验证 shouldJump()
returns 非零。
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 中的协议。特别是可选的协议方法。我认为这个问题可能与我的协议在不同的文件中定义/使用有关,但如果你将以下内容放在操场上,你会遇到同样的问题:
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
部分是否有效,但我希望它是默认值,以防未定义该方法。
如何让它工作?
我认为这是因为编译器知道 NSObject 没有 shouldJump
方法,所以调用 object.shouldJump?()
没有意义。您可以将 object
转换为您的协议:
let jump = (object as MyProtocol).shouldJump?() ?? true
Swift 是一种类型安全的语言。为了能够使用 shouldJump?()
,您首先必须有一个符合 MyProtocol
的对象。在这种情况下,您可以简单地转换类型:
let jump = (object as MyProtocol).shouldJump?() ?? true
您也可以将其存储在变量中:
let jumper = object as MyProtocol
let jump = jumper?.shouldJump() ?? true
你的 NSObject
符合 MyProtocol
,但是因为它没有实现可选的协议方法,所以编译器知道它没有 Selector
shouldJump
:
let object = NSObject()
object.conformsToProtocol(MyProtocol) // true
object.respondsToSelector("shouldJump") // false
解决这个问题的一种方法是在扩展中实现协议方法,以便对象执行该选择器:
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
并验证它是否响应可选 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 let
或 guard
来验证 shouldJump()
returns 非零。
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")
}
}
}