Хранилище приложений, пользовательское расширение, оболочка пользовательского свойства

Существует несколько способов управления данными на диске в среде iOS, например, такие библиотеки, как CoreData и Realm. Кроме того, те, кто работает с простым проектом или легким приложением, могут легко найти другие альтернативы: UserDefaults и FileManager.

UserDefaults и FileManager — популярные нативные API, и их может быть достаточно для большинства желаемых спецификаций. Однако, несмотря на его доступность, есть проблема, которую трудно игнорировать.

Ужасно использовать.

Представьте себе ситуацию, когда вы постоянно сохраняете и загружаете array с диска. Каждый раз, когда вы добавляете элемент в array, вы должны следовать процедуре, которая загружает, декодирует, добавляет, кодирует и, наконец, сохраняет данные. Это такая проблема.

В этом посте я покажу вам, как я справился с этой скучной, повторяющейся работой и сделал свои коды более чистыми и надежными.

Тогда давайте погрузимся!

Краткое содержание

  1. Собственная функция: AppStorage (iOS 14+)
  2. Пользовательский extension
  3. Оболочка пользовательского свойства

Хранилище приложений (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

Опять же, вам решать, дать ли вам второй шанс, выбрасывая и перехватывая ошибку где-то еще, или просто придерживаться политики, которая строго ограничивает неприемлемое поведение приложения.