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?)いますが、キャストによるオプションのバインディングはそこで失敗しています。

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

の代わりに別のものにのみアンラップする暗黙の としてあなたを疑ってdoorsいます。contextAny??OptionalCodeCollection

awake 関数内で使用するlet context = context as AnyObjectと、正しくアンラップできるはずです。

あなたが見ることができない、強制的にアンラップされたオプショナルのようなものだと考えてください。

このプレイグラウンドの最後の 2 つのコメントは、オプションが保持されている場所で遊ぶための例を他の人に与えるはずですが、オプションの型は消去され、ラップされています。

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 に答える