4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

値がオプショナル型のディクショナリにnilを代入する方法(Swift)

Last updated at Posted at 2024-04-22

はじめに

Swiftでは、ディクショナリの値に nil を代入するとキーごと削除されます。

var dict: [String: Int] = [:]
dict["foo"] = 1
dict["foo"] = nil
print(dict) // [:]

この動き自体は問題ありませんが、値がオプショナル型のときに nil を代入しようとしてもキーごと削除されます。

var dict: [String: Int?] = [:]
dict["foo"] = 1
dict["foo"] = nil
print(dict) // [:]

ではどうしたらキーごと削除せずに nil を代入できるでしょうか。

本記事では値がオプショナル型のディクショナリに nil を代入する方法を紹介します。

環境

  • OS: macOS Sonoma 14.3
  • Xcode: 15.3
  • Swift: 5.10

結論

.some(nil)nil を代入できます。

var dict: [String: Int?] = [:]
dict["foo"] = 1
dict["foo"] = .some(nil)
print(dict) // ["foo": nil]

他の方法

Optional<Int>.noneInt?.none でも nil を代入できますが、値の型に依存する書き方なので好みは分かれそうです。

var dict: [String: Int?] = [:]
dict["foo"] = 1
dict["foo"] = Optional<Int>.none
print(dict) // ["foo": nil]

dict["foo"] = Int?.none
print(dict) // ["foo": nil]

ちなみに Int?Optional<Int> のシンタックスシュガーなので、当然同じ結果になります。

解説

オプショナル型の実態は .none.some からなる列挙型のためです。

Swift.Optional
// 参考: Xcodeから参照した `Optional` 型の定義
@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)

    public init(_ some: Wrapped)
}

そのため .some(nil)Int?.nonenil を代入できます。

.none だとディクショナリで nil とみなされてキーごと削除されるので、 .none を使う場合は明示的に型を指定する必要があります。

注意

ディクショナリからオプショナル型の値を取り出す場合、最初のアンラップは値を取り出せるかどうかの判定になり、オプショナル型自体はアンラップされないのに注意です。

var dict: [String: Int?] = [:]
dict["foo"] = 1

if let foo = dict["foo"] {
    print(foo) // Optional(1)
}

オプショナル型を取り出すには2回アンラップします。

var dict: [String: Int?] = [:]
dict["foo"] = 1

- if let foo = dict["foo"] {
-     print(foo) // Optional(1)
+ if let foo = dict["foo"], let foo {
+     print(foo) // 1
}

おわりに

ディクショナリでオプショナル型を扱うときの参考になると嬉しいです :relaxed:

参考リンク

4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?