Больше никаких шаблонных кодов и повысьте возможность повторного использования
Представьте, что у вас есть приложение, и вы хотите реализовать функцию автоматического входа в систему. Таким образом, вы создаете UserDefaults
оболочку для инкапсуляции UserDefaults
логики чтения и записи.
Вы будете использовать оболочку UserDefaults
для отслеживания статуса включения / выключения автоматического входа, а также имени пользователя. Вот как обычно выглядит ваша UserDefaults
оболочка:
С помощью оболочки свойств, представленной в Swift 5.1, вы можете упростить свою оболочку UserDefaults
следующим образом:
Довольно круто, правда? Хотите узнать больше? Читать дальше…
Что такое Property Wrapper?
Прежде чем мы углубимся в подробности, давайте кратко познакомимся с тем, что такое оболочка свойств.
По сути, оболочка свойства - это общая структура данных, которая может перехватывать доступ для чтения / записи свойства, что позволяет добавлять настраиваемое поведение во время операции чтения / записи свойства.
Чтобы определить оболочку свойств, вы можете использовать ключевое слово @propertyWrapper
. Допустим, вы хотите иметь свойство строкового типа, при котором каждый раз при чтении или записи будет печататься консольный журнал.
Вы можете создать оболочку свойств с именем Printable
, как показано ниже:
Как видно из приведенного выше кода, оболочка свойств такая же, как и любой другой struct
в Swift. Однако wrappedValue
является обязательным при определении оболочки свойства.
Блок wrappedValue
get
и set
- это то место, где вы можете перехватить и выполнить желаемую операцию. В этом примере добавляется оператор печати для вывода значения get
или set
.
Вот как можно использовать оболочку свойств Printable
:
Обратите внимание, что мы используем символ @
для объявления переменной name
, заключенной в оболочку свойства. Если вы попробуете приведенный выше код на своей игровой площадке Xcode, вы увидите вывод консоли, как показано ниже:
Set value: Adidas Get value: Adidas
Обертка UserDefaults
Поняв, как работает оболочка свойств, мы готовы приступить к реализации нашей оболочки UserDefaults
. Напомним, наша оболочка свойств должна отслеживать статус включения / выключения автоматического входа, а также имя пользователя.
Используя концепцию, которую мы обсуждали выше, вы можете легко преобразовать оболочку свойства Printable
в оболочку свойства, которая будет записывать или читать из UserDefaults
во время операции чтения / записи свойства.
Здесь мы назвали нашу оболочку свойств Storage
. Он имеет два свойства: key
и defaultValue
.
key
будет ключом, который будет использоваться при чтении и записи в UserDefaults
, а defaultValue
- это значение, которое нужно вернуть, если в UserDefaults
нет значения.
Когда оболочка свойств Storage
готова, мы можем приступить к реализации оболочки UserDefaults
. Это довольно просто, нам просто нужно создать переменную имени пользователя, которая будет заключена в оболочку свойства Storage
.
Обратите внимание, как можно инициализировать оболочку свойств Storage
с помощью key
и defaultValue
.
При этом оболочка UserDefaults
, наконец, готова к использованию. Посмотрим на это в действии:
На этом этапе давайте попробуем добавить переменную enableAutoLogin
в нашу UserDefaults
оболочку.
Однако вы заметите, что произошли следующие две ошибки:
Cannot convert value of type ‘Bool’ to expected argument type ‘String’ Property type ‘Bool’ does not match that of the ‘wrappedValue’ property of its wrapper type ‘Storage’
Это связано с тем, что наша оболочка свойств в настоящее время поддерживает только тип данных String
. Чтобы исправить обе ошибки, нам нужно сделать нашу оболочку свойств универсальной.
Делаем Property Wrapper универсальным
Чтобы сделать оболочку свойств универсальной, мы должны изменить тип данных wrappedValue
оболочки свойств с String
на общий тип T
.
Кроме того, нам нужно будет обновить блок wrappedValue
get
, чтобы использовать общий способ чтения из UserDefaults
. Вот обновленная оболочка свойств:
Благодаря универсальной оболочке свойств наша оболочка UserDefaults
теперь может без проблем хранить логическое значение.
Хранение пользовательских объектов
На данный момент наша оболочка UserDefaults
может хранить любой базовый тип данных, например String
, Bool
, Int
, Float
, Array
и т. Д.
Но что, если нам нужно сохранить настраиваемый объект? В настоящее время мы столкнемся с ошибкой, если попытаемся сохранить настраиваемый объект. В этом разделе давайте сделаем нашу UserDefaults
оболочку более привлекательной, включив в нее поддержку настраиваемых объектов.
Идея здесь проста: мы будем хранить настраиваемый объект как данные в UserDefaults
. Для этого мы должны обновить общий тип Storage
оболочки свойств T
, чтобы он соответствовал протоколу Codable
.
После этого в блоке wrappedValue
set
мы будем использовать JSONEncoder
для преобразования настраиваемого объекта в данные и записи его в UserDefaults
.
Между тем, в блоке wrappedValue
get
мы будем использовать JSONDecoder
для преобразования данных, полученных из UserDefaults
, обратно в нужный тип данных.
Вот обновленная оболочка свойств Storage
:
Чтобы увидеть, как можно использовать обновленную оболочку свойств Storage
, давайте взглянем на следующий пример.
Представьте, что вам нужно сохранить информацию о пользователе, возвращаемую сервером после успешного входа в систему.
Во-первых, вам понадобится структура для хранения информации о пользователе, возвращаемой сервером. Структура должна соответствовать протоколу Codable
, чтобы ее можно было преобразовать в данные и сохранить в UserDefaults
.
Следующим шагом является объявление объекта User
в оболочке UserDefaults
:
Вот и все! Обертка UserDefaults
теперь может хранить пользовательские объекты.
Хранение зашифрованной строки
Мы прошли долгий путь, сделав нашу UserDefaults
оболочку универсальной и способной хранить практически все, что мы пожелаем.
Но подождите, а что, если вам нужно сохранить пароль пользователя или какие-либо конфиденциальные данные с помощью оболочки UserDefaults
?
В настоящее время все строки, которые хранятся в нашей UserDefaults
оболочке, представляют собой простой текст, и все мы знаем, что хранить пароли в виде простого текста - крайне плохая практика!
Для этого мы можем использовать концепцию, которую мы только что обсудили, создать другую оболочку свойства, которая зашифрует ее значение перед установкой в UserDefaults
. Мы назовем эту оболочку свойств EncryptedStringStorage
.
В демонстрационных целях шифрование, которое мы здесь выполняем, представляет собой простую операцию обращения всей строки. Способ использования оболочки свойств EncryptedStringStorage
довольно прост:
Заключение
Используя оболочку свойств, представленную в Swift 5.1, мы сократили много шаблонного кода в нашей оболочке UserDefaults
.
Кроме того, оболочку свойств Storage
и оболочку свойств EncryptedStringStorage
также можно повторно использовать в других проектах.
В следующий раз, когда вам понадобится создать оболочку UserDefaults
, попробуйте метод оболочки свойств, я уверен, вам она понравится.
Вы можете найти полный исходный код здесь.
Надеюсь, эта статья окажется для вас полезной. Не стесняйтесь оставлять комментарии, если у вас есть какие-либо вопросы или мысли относительно оболочки UserDefaults
.
Спасибо за чтение и удачного кодирования!