Небольшое расширение для Foundation, упрощающее разработку.

В процессе разработки довольно часто программист сталкивается со словарем типа [String: Any] (ответ сервера в виде json) или [AnyHashable: Any] (userInfo при получении push уведомления). В то же время иногда необходимо сформировать словарь данного типа, при этом нежелательно каждый раз указывать ключ в виде String. Небольшое расширение для словаря, представленное ниже, решает данную проблему и несколько упрощает процесс разработки.

Определение ключей в отдельном enum

В результате получить значение словаря можно как с помощью строки, так и с помощью case'а перечисления:

let dict: [String: Any] = ["data": 1, "id": 2, "type": 3]
let result = dict["type"]
let sameResult = dict[.type]

Приведение к нужному типу

let dict: [String: Any] = ["data": 1, "id": 2, "type": 3]
let result = dict["id"] as? Int

Куда удобней вынести downcast в расширение, благо язык swift имеет широкие возможности для реализации. Необходимо объявить subscript с обобщением (generic):

При наличии такого subscript'а нет необходимости приведения значения к нужному типу. Соответственно используются все возможности swift'а по неявному определению типа:

let dict: [String: Any] = ["data": 1, "id": 2, "type": 3]
someMethod(optionalIntegerArgument: dict[.id])
XCTAssertEqual(dict[.type], 3)let result: Int? = dict["type"]
let sameResult: Int? = dict[.type]

Формирование словаря

По-сути данное расширение позволяет выполнять mapping к любому rawValue, реализующему Hashable протокол, не только к строкам. Поэтому расширение является чуть более универсальным. Тем не менее поставленная задача решена достаточно изящно:

enum Payment: String {
case cash, card, credit
}

let dict: [Payment: Double] = [.cash: 10, .card: 20, .credit: 0]
let result = dict.mappedToRawValues
XCTAssertEqual(result, ["cash": 10.0, "card": 20.0, "credit": 0.0])

Заключение