为什么我还需要打开Swift字典值呢?

时间:2015-12-02 21:10:52

标签: swift optional

public IEnumerator MyLoop()
{
    while (fracJourney <= 1)
    {
        float distCovered = (Time.time - startTime) * speed;
        fracJourney = distCovered / journeyLength;
        Debug.Log(fracJourney);
        transform.position = Vector3.Lerp(startPoint, endPoint, speed);

        yield return null;     //< --- yield out and let a frame pass
    }
}

我收到错误:class X { static let global: [String:String] = [ "x":"x data", "y":"y data", "z":"z data" ] func test(){ let type = "x" var data:String = X.global[type]! } }

为什么我需要在Value of optional type 'String?' not unwrapped之后使用!?我在字典中没有使用任何可选项?

被修改

即使该类型可能不存在X.global[type],强制解包仍会在运行时崩溃。更好的方法可能是:

X.global[type]

但是Xcode通过暗示可选类型给了我错误的想法。

2 个答案:

答案 0 :(得分:7)

Dictionary accessor返回其值类型的可选项,因为它不“知道”运行时字典中是否存在某个键。如果它存在,则返回相关值,但如果不存在则返回nil

来自documentation

  

您还可以使用下标语法从字典中检索特定键的值。因为可以请求不存在值的键,所以字典的下标返回字典值类型的可选值。如果字典包含所请求键的值,则下标返回包含该键的现有值的可选值。否则,下标返回nil ...

为了正确处理这种情况,你需要打开返回的可选项。

有几种方法:

选项1:

func test(){
    let type = "x"
    if var data = X.global[type] {
        // Do something with data
    }
}

选项2:

func test(){
    let type = "x"
    guard var data = X.global[type] else { 
        // Handle missing value for "type", then either "return" or "break"
    }

    // Do something with data
}

选项3:

func test(){
    let type = "x"
    var data = X.global[type] ?? "Default value for missing keys"
}

答案 1 :(得分:0)

如果我们查看Dictionary实施,subscript会将ValueType作为可选项返回,因为它不知道key是否存在:

//Reading a key that is not present in `self` yields `nil`.
//Writing `nil` as the value for a given key erases that key from `self`.
subscript (key: KeyType) -> ValueType?

因此,当我们尝试从Dictionary获取值时,我们将其作为subscript中的可选项获取;那就是我们必须打开可选项来获取底层对象。如前面的答案所述,选项2是首选。

guard var data = X.global[type] else { 
    //key = 'type' doesn't exists
}
//key exists so do something with 'data'