Хранилище приложений, пользовательское расширение, оболочка пользовательского свойства
Существует несколько способов управления данными на диске в среде iOS, например, такие библиотеки, как CoreData и Realm. Кроме того, те, кто работает с простым проектом или легким приложением, могут легко найти другие альтернативы: UserDefaults
и FileManager
.
UserDefaults
и FileManager
— популярные нативные API, и их может быть достаточно для большинства желаемых спецификаций. Однако, несмотря на его доступность, есть проблема, которую трудно игнорировать.
Ужасно использовать.
Представьте себе ситуацию, когда вы постоянно сохраняете и загружаете array
с диска. Каждый раз, когда вы добавляете элемент в array
, вы должны следовать процедуре, которая загружает, декодирует, добавляет, кодирует и, наконец, сохраняет данные. Это такая проблема.
В этом посте я покажу вам, как я справился с этой скучной, повторяющейся работой и сделал свои коды более чистыми и надежными.
Тогда давайте погрузимся!
Краткое содержание
- Собственная функция:
AppStorage
(iOS 14+) - Пользовательский
extension
- Оболочка пользовательского свойства
Хранилище приложений (iOS 14+)
На самом деле у нас уже есть отличное решение AppStorage
. С выпуском iOS 14 Apple представила оболочку свойств под названием AppStorage
, которая упрощает огромную часть обработки данных на диске.
Это краткий пример, показывающий компонент пользовательского интерфейса, который изменяется в зависимости от состояния сохраненного значения isFirst
.
Все, что мне нужно сделать, это обернуть переменную @Appstorage
и присвоить ей уникальный строковый ключ. Затем он будет обрабатывать большинство раздражающих задач ввода-вывода для нас, и в конечном итоге данные могут сохраняться даже после того, как приложение будет уничтожено.
Кажется, это отличное решение, которое объединяет все преимущества UserDefault
и устраняет большинство недостатков. Тем не менее, есть некоторые сведения, которые необходимо знать перед его использованием.
Он поддерживает только Int
, Double
, String
, URL
, Data
(включая необязательные). Это означает, что если вы хотите сохранить struct
, class
или array
, вам все равно нужно повторить encoding
, decoding
.
Поддерживается начиная с iOS 14.Это то, от чего мы всегда страдали. Кроме того, для его использования необходимо использовать SwiftUI.
Пользовательское расширение
Концепция пользовательских расширений заключается в том, чтобы попытаться максимально сохранить методы в том виде, в котором они были изначально написаны. Для этого нам нужно иметь возможность добавить элемент в массив, хранящийся на диске, например:
var testArray = [Int]() testArray.append(3, storage: "testArrayKey")
Вот реализация:
Я перегрузил два часто используемых метода append
и removeAll
. Отличие от оригинального только в том, что он имеет дополнительный параметр storage
, который будет использоваться для пути хранения FileManager
.
Вот простое использование тестовых кодов:
С ними вроде нет проблем. Тем не менее, есть несколько проблем, которые легко пропустить.
Во-первых, прогнозирование начального значения сбивает с толку. Давайтена этот раз рассмотрим случай сбоя.
Этот пример показывает, что вы можете получить непредвиденные ошибки, когда пытаетесь изменить значение после того, как переменная уже была где-то инициализирована. Это происходит потому, что он игнорирует новое значение и загружает сохраненные данные вместо переопределения переменной с новым значением. У AppStorage
тоже такая же проблема.
Чтобы решить эту проблему, вы можете выбрать между запросом дополнительных параметров или просто предупреждением пользователя о том, что произойдет ошибка.
Во-вторых, вы должны реализовывать все, что вам нужно, одну за другой. На этот раз я написал коды только для массива Codable
, но если вам нужно больше методов, таких как filter
, map
или даже struct
, class
, вам следует повторить те же действия для огромного количества кодов.
Оболочка пользовательского свойства
Чтобы решить эти проблемы, с которыми столкнулся extension
, я придумал новое решение: оболочки свойств.
Вот несколько примеров использования тестовых кодов:
По сравнению с extension
имеет три преимущества.
Во-первых, вам не нужно перегружать все необходимые методы. Обернув переменную с помощью Stored
, вы получите постоянное хранилище со всеми функциями, которые изначально были у его типа, потому что он использует общий тип.
Во-вторых, это предотвращает появление «непредсказуемой ошибки начального значения», которую мы видели в пользовательском extension
. Вот тестовые коды, чтобы проверить это.
Третий, таким образом, он становится более надежным. Мы можем обработать конкретную ошибку, вызвав исключение. Например, мы можем привести к сбою приложения при попытке использовать неинициализированное значение.
func testStoredWrapperNotStoredBefore() throws { @Stored("NotInitialized") var storedQueue: [String] } // Throws fatalError
Опять же, вам решать, дать ли вам второй шанс, выбрасывая и перехватывая ошибку где-то еще, или просто придерживаться политики, которая строго ограничивает неприемлемое поведение приложения.