Как реализовать функцию setValue для обновления значения по ключу
Что проверяют
Знание Dictionary в Swift, семантики значений и потокобезопасности. Формулировка расплывчатая, поэтому интервьюер смотрит, уточните ли вы требования: плоский словарь, вложенный путь вида user.address.city или свойство модели по ключу. Следом почти всегда спрашивают про доступ из нескольких потоков.
Как отвечать
Базовый вариант делайте обобщённым, KeyValueStore<Key: Hashable, Value>, а не на [String: Any]:
- вставка и замена:
storage[key] = valueдобавляет или перезаписывает.updateValue(_:forKey:)делает то же и возвращает старое значение, это удобно для отмены и логов; - удаление:
storage[key] = nilилиremoveValue(forKey:); - семантика значения:
Dictionaryэто структура с копированием при записи. Вstructметод помечаютmutating, а чтобы изменить чужой словарь, его передают какinout; - вложенный путь: рекурсия по компонентам ключа. Вложенный словарь достаётся копией, поэтому после изменения его нужно записать обратно на свой уровень, иначе правка потеряется;
- типобезопасная альтернатива:
WritableKeyPath, напримерfunc set<T>(_ value: T, at path: WritableKeyPath<Settings, T>). Компилятор проверит и сам ключ, и тип значения; - потоки:
Dictionaryне потокобезопасен. Хранилище делаютactor, тогда обращения идут черезawait, либо защищают блокировкой:NSLock,OSAllocatedUnfairLock, в Swift 6Mutexиз модуляSynchronization.
Ошибки вроде пустого ключа возвращайте через throws, а не печатайте в консоль.
Где спотыкаются
Берут [String: Any] и print внутри метода. Проверка типов теряется, при чтении приходится писать as? на каждом шаге, а ошибка тонет в логах вместо того, чтобы дойти до вызывающего кода.
Не знают особенности словаря с опциональными значениями. В [String: Int?] присваивание dict[key] = nil удаляет ключ, а не сохраняет пустое значение. Чтобы сохранить именно nil, нужен updateValue(nil, forKey:).
Называют метод setValue(_:forKey:) в наследнике NSObject. Это имя уже занято KVC: достаточно промахнуться с типом параметра, и вызовется системная реализация, которая на неизвестном ключе падает с NSUnknownKeyException.