任何不一致的铸造?在可选绑定期间进入Swift中的协议

时间:2016-09-20 02:50:43

标签: swift casting swift-protocols watch-os-3 optional-binding

我遇到了一些Swift Optional Binding的问题,并将其转换为协议。我在操场上有以下代码,工作正常。

protocol CodeCollection {
    var name: String { get }
    var codes: [String] { get }
}

struct VirtualDoors: CodeCollection {
    var name = "Virtual Doors"
    var codes: [String] = ["doorNumba1", "doorNumba2"]
}

// Instance of VirtualDoors
let doors = VirtualDoors()

// cast into Any? like what awake(withContext context: Any?) receives
var context = doors as Any?

print(context)
if let newDoors = context as? CodeCollection {
    // Works as expected
    print(newDoors)
}

我在watchKit中使用与awake(withContext context: Any?)中传递的信息完全相同的协议和结构,并且使用强制转换的可选绑定在那里失败。

override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    // Just checking to make sure the expected item is in fact being passed in
    print(context)
    // "Optional(VirtualDoors(name: "Virtual Doors", codes: ["doorNumba1", "doorNumba2"]))\n"

    if let newDoors = context as? CodeCollection {
        self.collection = newDoors
        print("Context Casting Success")
    } else {
        // Casting always fails
        print("Context Casting Fail")
    }
}

如果有人能告诉我为什么它在游乐场工作而不是在watchKit类方法中,我真的很感激。

我觉得我错过了一些非常明显的东西。

1 个答案:

答案 0 :(得分:1)

我怀疑你doorscontext为隐式Any??,只能解包到另一个Optional而不是CodeCollection

如果你在清醒功能中使用let context = context as AnyObject,那么应该能够正确打开它。

把它想象成一个你不能看到的力量未被打开的选项。

这个游乐场的最后两个评论应该给别人一个例子来说明保留选项的位置,但是可选类型被​​删除和包装。

import Foundation

protocol Target {
    var name: String { get }
}

func takesAnyOptional(context: Any?) -> String? {
    return (context as? Target)?.name
}

struct Source: Target {
    let name = "Source"
}

let solid = Source()
print((solid as Target).name)
takesAnyOptional(context: solid)

let solid_any = solid as Any
print((solid_any as? Target)?.name)
takesAnyOptional(context: solid_any)
takesAnyOptional(context: solid_any as Any?)

let solid_anyOpt = solid as Any?
print((solid_anyOpt as? Target)?.name)
takesAnyOptional(context: solid_anyOpt)
takesAnyOptional(context: solid_anyOpt as Any) // -> double optional -> nil

let solid_anyOpt_any = solid_anyOpt as Any
takesAnyOptional(context: solid_anyOpt_any) // -> double optional -> nil