【问题标题】:Bound value in a conditional binding must be of Optional Type条件绑定中的绑定值必须是可选类型
【发布时间】:2014-06-08 21:27:13
【问题描述】:

我定义了一个协议:

protocol Usable {
    func use()
}

以及符合该协议的类

class Thing: Usable {
    func use () {
        println ("you use the thing")
    }
}

我想以编程方式测试 Thing 类是否符合 Usable 协议。

let thing = Thing()

// Check whether or not a class is useable
if let usableThing = thing as Usable { // error here
    usableThing.use()
}
else {
    println("can't use that")
}

但我得到了错误

Bound value in a conditional binding must be of Optional Type

如果我尝试

let thing:Thing? = Thing()

我得到了错误

Cannot downcast from 'Thing?' to non-@objc protocol type 'Usable'

然后我将@objc 添加到协议并得到错误

Forced downcast in conditional binding produces non-optional type 'Usable'

此时我在as之后添加?,最终修复了错误。

如何通过非@objc 协议的条件绑定来实现此功能,就像在“Advanced Swift”2014 WWDC 视频中一样?

【问题讨论】:

  • 我确定这是一个人为的案例,但它没有任何意义。编译器已经明确知道该事物遵守 Usable 协议。没有必要对其进行测试,因为测试永远不会失败。
  • @drewag 如果我有一堆类,有些符合,有些不符合。然后我可能希望能够检查每个类是否符合。无论如何,这只是一个错误的演示,很明显 Thing 类符合。
  • 是的,如果您使用 AnyObject 作为事物的类型,我找不到检查它是否实现 Usable 的方法(这就是我没有提供答案的原因)。如果东西是 AnyObject 而 Usable 不是 objc 协议,则下面的答案都无法编译

标签: protocols swift conditional-binding


【解决方案1】:

您可以通过将强制转换设为可用来编译它吗?而不是作为可用,像这样:

// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
    usableThing.use()
}
else {
    println("can't use that")
}

【讨论】:

  • 这在像let thing : AnyObject = Thing() 这样实际上有意义的场景中不起作用然后你会得到一个向下转换的错误
  • 这应该是thing as? Usable 而不是thing as Usable?
【解决方案2】:

正如 Swift 文档中提到的,is 运算符是您完成这项工作所需要的人:

is 运算符在运行时检查表达式是否为 指定的类型。如果是,则返回 true;否则,它返回 假的。

在编译时不能知道检查是真还是假。

因此,您通常需要以下测试:

if thing is Usable { 
    usableThing.use()
} else {
    println("can't use that")
}

但是,正如文档所指定的,Swift 可以在编译时检测到表达式始终为真,并声明错误以帮助开发人员。

【讨论】:

  • 但我使用is 收到“测试始终为真”警告。
【解决方案3】:

这在操场上对我有用

protocol Usable {
    func use()
}

class Thing: Usable {
    func use () {
        println ("you use the thing")
    }
}

let thing = Thing()
let testThing : AnyObject = thing as AnyObject

if let otherThing = testThing as? Thing {
    otherThing.use()
} else {
    println("can't use that")
}

【讨论】:

  • 已验证,但我发现您在声明“testThing”时不需要强制转换“as AnyObject” - 有人检查吗?
  • 赞成,因为这是我想使用的成语。请注意,您使用的变量必须是您想要的协议或类的超类。
【解决方案4】:

你得到了

Bound value in a conditional binding must be of Optional Type

因为thing as Usable 必须返回一个可选类型,所以将其设为as? 应该可以解决问题。不幸的是,由于某些奇怪的原因,该错误仍然存​​在。无论如何,我发现让它工作的一种解决方法是提取 if 语句中的变量赋值

let thing = Thing()

let usableThing = thing as? Usable

if useableThing { 
    usableThing!.use()
}
else {
    println("can't use that")
}

【讨论】:

  • 这在像let thing : AnyObject = Thing() 这样实际上有意义的场景中不起作用然后你会因为它不是一个 objc 协议而得到一个向下转换的错误
  • 好吧,那他应该做thing.use?()
  • 然后得到错误 AnyObject does not have a member named use()
  • 其实没有,如果use()不存在则返回nil。
  • 就像objective-c一样,你需要从你的协议中继承NSObjectProtocol才能让respondToSelector工作。抱歉没有明确提及。
【解决方案5】:

swift 协议在 Playgrounds 的第一个测试版中不起作用,请尝试构建一个真实的项目。

【讨论】:

  • 您能否提供一个参考,说明您从哪里获得这些知识?
  • 刚刚得到了在操场上工作的协议,也许我的比较新
猜你喜欢
  • 2015-09-29
  • 2015-01-29
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
相关资源
最近更新 更多