> Как реализовать функции setValue и getValue с поддержкой nil значений (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Revolut
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Для поддержки nil значений в setValue/getValue нужно использовать Optional (?) в сигнатуре методов и отличать "ключ отсутствует" от "значение nil". Хранение лучше организовать через словарь [Key: Value], где Value - Optional, а доступ через subscript с проверкой наличия ключа. В Swift это естественно решается через enum с ассоциированными значениями или через Dictionary с Optional значениями и отдельным флагом существования ключа.
Подробное объяснение
Проблема возникает из-за того, что Dictionary[Key] возвращает Value?, где nil означает и отсутствие ключа, и хранимое nil-значение. Для различения этих случаев нужно хранить Optional внутри Optional: [Key: Value?]. Тогда:
dict[key] == nil- ключ отсутствуетdict[key] == .some(nil)- ключ есть, значение nildict[key] == .some(.some(value))- ключ есть, значение есть
Альтернативный подход - использовать enum Storage<Value> { case absent, present(Value?) } и словарь [Key: Storage<Value>]. Это более явно и типобезопасно.
Для setValue/getValue сигнатуры:
SWIFTfunc setValue(_ value: Value?, forKey key: Key)func getValue(forKey key: Key) -> Value??
Второй возвращает Value?? - внешний Optional говорит о наличии ключа, внутренний - о значении.
На практике
В реальном iOS-коде такая задача возникает при работе с UserDefaults, кэшами или конфигурационными хранилищами, где нужно отличать "не задано" от "задано как nil". Часто используют обёртку PropertyWrapper или generic-класс хранилища.
Для UserDefaults есть нюанс: set(nil, forKey:) удаляет ключ, поэтому для хранения nil нужно использовать sentinel-значение (например, специальную строку) или отдельный словарь флагов.
Пример кода
SWIFTstruct KeyValueStore<Key: Hashable, Value> {private var storage: [Key: Value?] = [:]mutating func setValue(_ value: Value?, forKey key: Key) {storage[key] = value}func getValue(forKey key: Key) -> Value?? {return storage[key] // .some(nil) - ключ есть, nil; .none - ключа нет}func hasKey(_ key: Key) -> Bool {return storage[key] != nil}}// Использованиеvar store = KeyValueStore<String, Int>()store.setValue(nil, forKey: "a")store.setValue(5, forKey: "b")let a = store.getValue(forKey: "a") // Optional(Optional(nil))let b = store.getValue(forKey: "b") // Optional(Optional(5))let c = store.getValue(forKey: "c") // nilswitch store.getValue(forKey: "a") {case .some(.some(let value)): print("value: \(value)")case .some(.none): print("key exists, value is nil")case .none: print("key missing")}
Как отвечать на собеседовании
Начни с постановки проблемы: Dictionary не различает отсутствие ключа и nil-значение. Затем предложи два решения: [Key: Value?] и enum Storage. Объясни trade-off: первый проще, второй - безопаснее и читаемее. Покажи сигнатуры с Value?? и объясни семантику каждого уровня Optional. Упомяни, что в SwiftUI/Combine часто используют Published<Value?> с отдельным флагом наличия. Если спросят про UserDefaults - расскажи про sentinel-значения.
Что проверяет интервьюер
- Понимание Optional-вложенности и её семантики
- Умение проектировать API с учётом edge case
- Знание Swift-типов и их поведения (Dictionary, Optional)
- Способность объяснить trade-off между простотой и типобезопасностью
- Практическое мышление: как это применить в реальном iOS-коде
Типичные ошибки
- Использование
[Key: Value]без учёта nil - потеря информации о наличии ключа - Возврат
Value?вместоValue??- невозможно отличить "нет ключа" от "nil" - Забывают, что
dict[key] = nilудаляет ключ, а не сохраняет nil - Путают
.some(nil)иnilпри switch по Optional - Не учитывают, что
Dictionarysubscript сdefaultпараметром тоже не решает проблему различения - Предлагают хранить
NSNullкак маркер - это не Swift-идиоматично и ломает типобезопасность
> Похожие задачи по mobile
Какие типы данных относятся к стеку, а какие к куче
Что такое side table
Как реализовать unit test для функции записи данных в файл
Как реализовать функцию умножения числа на десять с обработкой символов
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью