LoginSignup
3
2

More than 1 year has passed since last update.

Swiftで[String: Any]型の等価性チェックをする

Last updated at Posted at 2022-07-02

Swiftで以下のコードはコンパイルエラーになります。
Any型がEquatableに準拠していないというのが理由です。

let dict1: [String: Any] = ["foo": "bar"]
let dict2: [String: Any] = ["foo": "bar"]
print(dict1 == dict2)  // Protocol 'Any' as a type cannot conform to 'Equatable'

そこで、以下のように[String: Any]をNSDictionaryにキャストして比較します。
こうするとコンパイルすることができ、結果はtrueになります。
※この方法では正しい比較ができないケースがあります。次項を参照してください

let dict1: [String: Any] = ["foo": "bar"]
let dict2: [String: Any] = ["foo": "bar"]
print(dict1 as NSDictionary == dict2 as NSDictionary)  // true

SwiftではDictionaryとNSDictionaryをシームレスに相互変換することができます。

そして、NSDictionaryはNSObjectのサブクラスであるため、Equatableに準拠しています。

これによって上記の比較が可能になります。


2023/1/6追記

以下の例は一見trueになりそうですが、結果はfalseになります。

struct Bar: Equatable {
  let bar: Int
}

let dict1: [String: Any] = ["foo": Bar(bar: 1)]
let dict2: [String: Any] = ["foo": Bar(bar: 1)]
print(dict1 as NSDictionary == dict2 as NSDictionary)  // false

BarをHashableに準拠させるとtrueになります。

struct Bar: Hashable {
  let bar: Int
}

let dict1: [String: Any] = ["foo": Bar(bar: 1)]
let dict2: [String: Any] = ["foo": Bar(bar: 1)]
print(dict1 as NSDictionary == dict2 as NSDictionary)  // true

NSDictionary同士の比較はNSObjectProtocolのisEqual(_:)メソッドを使用しています。
このメソッドは2つのオブジェクトのハッシュ値が同じである場合にtrueを返すようになっています。
Hashableに準拠させることでハッシュの比較が正しくできるようになり、期待通りの結果が得られるようになるのだと思います。


参考

3
2
0

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
3
2