3

我在某些 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?)并且与 cast 的可选绑定在那里失败。

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 类方法中无效,我将不胜感激。

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

4

1 回答 1

1

我怀疑你doorscontext一个隐含的Any??,它只会展开到另一个Optional而不是CodeCollection.

如果你let context = context as AnyObject在 awake 函数内部使用,那么应该能够正确解包它。

把它想象成一个你看不到的强制解包选项。

这个操场的最后两条评论应该给其他人一个例子,让其他人可以使用保留选项的地方,但可选类型被​​擦除和包装。

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
于 2016-09-20T17:11:44.653 回答