Как реализовать функцию, которая возвращает nil или значение из словаря
Что проверяют
Понимаете ли вы, что сабскрипт словаря в Swift уже возвращает опционал, и умеете ли писать обобщённый код вместо [String: Any]. Следом спрашивают про значение по умолчанию и про неприятный случай, когда в словаре лежат опционалы.
Как отвечать
Базовый ответ короткий: dict[key] имеет тип Value?, и при отсутствии ключа это nil. Отдельная функция имеет смысл, если добавляет логику: проверку типа, значение по умолчанию, логирование. Пишите её дженериком, а не через Any:
- сигнатура:
func value<Key: Hashable, Value>(in dict: [Key: Value], for key: Key) -> Value?. Тип сохраняется, приведениеas?на вызывающей стороне не нужно; - значение по умолчанию:
dict[key, default: 0]возвращает не опционал. На записи удобноcounts[word, default: 0] += 1; - извлечение:
if let,guard letили??. Начиная со Swift 5.7 есть краткая формаif let name { ... }; - разнородные данные: если значения всё же
Any, приведениеas? Stringвозвращаетnilи на отсутствующий ключ, и на неверный тип. Когда эти случаи важно различать, возвращайтеResultили бросайте ошибку.
Хорошо показать тонкость со словарём опционалов. У [String: Int?] сабскрипт возвращает Int??: внешний уровень говорит, есть ли ключ, внутренний, лежит ли в нём nil. Присваивание dict["a"] = nil удаляет ключ, а чтобы сохранить сам nil, нужно dict["a"] = .some(nil) или dict.updateValue(nil, forKey: "a").
Для данных из JSON чаще правильнее не словарь [String: Any], а структура с Codable: компилятор проверит типы вместо вас.
Где спотыкаются
Используют принудительное извлечение dict[key]!. На отсутствующем ключе приложение падает, и на ревью это заметят первым делом.
Делают функцию с [String: Any] и Any?, теряя типы. Потом каждый вызов обрастает as?, а ошибки типов видны только в рантайме.
Не знают про двойной опционал и удаление через nil. Код, который записывает nil в словарь опционалов, неожиданно теряет ключ, и keys.count расходится с ожиданием.