简体   繁体   English

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

[英]Inconsistent Casting of Any? into a Protocol in Swift during Optional Binding

I'm having trouble with some Swift Optional Binding with a cast into a protocol. 我遇到了一些Swift Optional Binding与一个转换为协议的问题。 I have the following code in a playground that works fine. 我在操场上有以下代码,工作正常。

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)
}

I'm using the exact same protocol and struct in watchKit as a piece of info passed in awake(withContext context: Any?) and the optional binding with cast is failing there. 我在watchKit中使用完全相同的协议和结构作为awake(withContext context: Any?)传递的信息awake(withContext context: Any?)并且使用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")
    }
}

I'd be really appreciative if someone could tell me why this is working in the playground but not in the watchKit class method. 如果有人能告诉我为什么它在操场上工作而不是在watchKit类方法中,我真的很感激。

I feel like I am missing something really obvious. 我觉得我错过了一些非常明显的东西。

I suspect you doors to context as an implicit Any?? 我怀疑你context doors是隐含的Any?? , which only unwraps to another Optional instead of CodeCollection . ,仅解包到另一个Optional而不是CodeCollection

If you use let context = context as AnyObject inside the awake function, then should be able to unwrap it correctly. 如果在唤醒函数中使用let context = context as AnyObject ,那么应该能够正确地解包它。

Think of it like an force-unwraped optional that you don't get to see. 可以把它想象成一种你没有看到的力量未被打开的选项。

The last two comments of this playground should give others an example to play with where the optionals are kept, but the optional type is erased and wrapped. 这个游乐场的最后两个评论应该给其他人一个例子来保存选项,但是可选类型被​​删除和包装。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM