48591

[code]

    let hoge: String? = nil
    let foo: String? = "foo"
    
    var dict = [String: Any]()
    
    if let hoge = hoge {
        dict["hoge"] = hoge
    }
    
    if let foo = foo {
        dict["foo"] = foo
    }
    
    print(dict) // => ["foo": "foo"]
    
[/code]

上記のような  
`オプショナルな値`が入っていた場合のみ`アンラップ`して`ディクショナリ`に登録していく処理をもっとシンプルにしたいと考え、いろいろ試していると下記のような挙動を発見しました。

[code]

    let hoge: String? = nil
    let foo: String? = "foo"
    
    var dict = [String: Any]()
    
    dict["hoge"] = hoge
    dict["foo"] = foo
    
    print(dict) // => ["foo": "foo"]
    
[/code]

`nil`である `dict["hoge"] = hoge` の処理が無視されているようです。

これは安全な書き方なのでしょうか？

<https://developer.apple.com/documentation/swift/dictionary>

> Update an existing value by assigning a new value to a key that already
> exists in the dictionary. If you assign nil to an existing key, the key and
> its associated value are removed.

によるとnilの代入は削除を意味しているようです。  
削除ではない今回のような初期化ぽい使い方をしても問題ないでしょうか？


CC BY-SA 4.0
2018-09-20T07:22:13.300
48585
2018-09-20T08:46:25.683
2018-09-20T08:35:13.590
19110
9008
question
swift swift4
勝手にnilが無視される挙動を使って安全？


**_削除ではない今回のような初期化ぽい使い方をしても問題ないでしょうか？_**

「問題ない」をどのように捉えるかによります。ご自身が確かめられたように、現在のSwiftで、そのコードの書き方なら問題ないようです。

ただ、`Any`は`nil`を含む任意の値を格納しうる型なので、今後のSwiftでも確実にそのような動作になるか、と言うのはリンク先の記載からは読み取れません。

例えば、ほとんど同じ意味のはずと思われているこちらのコードは、以下のような結果になります。

[code]

    let dict2: [String: Any] = [
        "hoge": hoge,
        "foo": foo,
    ]
    print(dict2) //-> ["hoge": nil, "foo": Optional("foo")]
    
[/code]

Swiftの`nil`には実際には型があって、`String?`型の`nil`と`Any?`型の`nil`は別物なので、「`Any?`型の`nil`ではなく`String?`型の`nil`を代入しているのに、そのような動作になるのはバグではないか?」と言うバグ報告が上がったら、「修正」される可能性もありそうです。

また、現在のSwiftには、[Warn when Optional converts to Any, and bridge Optional As Its
Payload Or NSNull](https://github.com/apple/swift-
evolution/blob/master/proposals/0140-bridge-optional-to-
nsnull.md)という仕様が取り込まれています。`[String: Any]`がObjective-
C側に`NSDictionary`として渡される場合、`String?`型の`nil`が`NSNull`にならずに、エントリー削除になってしまうのは、この仕様とも相性が悪そうです。

この辺り、swift.orgに投稿すれば(英語でってことになりますが)、Swift言語開発Teamのメンバーから直接意見をもらえるかもしれません。

と言うわけで、何らかのドキュメントに明示されるまでは、

**「値が`nil`の場合にはエントリー自体を追加したくない」と言う場合、面倒がらずに上のように書いた方が良い**

ように思われます。(将来のSwiftのバージョンで動作が変更になった場合、表に現れる影響から原因を探るのはかなり大変になりそうです。)


CC BY-SA 4.0
2018-09-20T08:46:25.683
48591
2018-09-20T08:46:25.683
13972
48585
answer