Моделирование Состояния Приложения С Использованием Объектов Хранилища В Swiftui

На этой неделе я хочу поговорить о моделировании уровней данных в SwiftUI. Я уже закончил работу над своим самым первым приложением, которое создаю, используя только SwiftUI. Теперь я могу поделиться методом создания слоя модели с использованием объектов Store, который я использовал при разработке приложения NapBot.



Хранить объект

Объекты хранилища отвечают за сохранение состояния и выполнение действий по его изменению.

Вы можете иметь столько объектов Store, сколько вам нужно, желательно, чтобы они были простыми и отвечали за небольшую часть состояния вашего приложения.

Например, у вас может быть НастройкиМагазин сохранить состояние пользовательских настроек и TodoStore для сохранения пользовательских задач.

Чтобы создать объект Store, вам необходимо создать класс, соответствующий протоколу НаблюдаемыйОбъект .

Протокол ObservableObject позволяет SwiftUI наблюдать и реагировать на изменения данных.

Чтобы узнать больше о ObservableObject, прочтите статью " Управление потоками данных в SwiftUI ".

Давайте рассмотрим простой пример объекта НастройкиМагазин .

  
  
  
  
   

import Foundation import Combine final class SettingsStore: ObservableObject { let objectWillChange = PassthroughSubject<Void, Never>() @UserDefault(Constants.UserDefaults.sleepGoal, defaultValue: 8.0) var sleepGoal: Double @UserDefault(Constants.UserDefaults.notifications, defaultValue: true) var isNotificationsEnabled: Bool private var didChangeCancellable: AnyCancellable? override init() { super.init() didChangeCancellable = NotificationCenter.default .

publisher(for: UserDefaults.didChangeNotification) .

map { _ in () } .

receive(on: DispatchQueue.main) .

subscribe(objectWillChange) } }

В приведенном выше примере кода у нас есть класс НастройкиМагазин , который обеспечивает доступ к пользовательским настройкам.

Мы также используем DidChangeNotification чтобы уведомлять SwiftUI всякий раз, когда пользователь меняет настройки по умолчанию.



Расширенное использование

Давайте рассмотрим другое использование объекта магазина, создав простое приложение.

Делать .

Нам нужно создать объект хранилища, который хранит список задач и предоставляет действия для их изменения, например их удаление и фильтрацию.



import Foundation import Combine struct Todo: Identifiable, Hashable { let id = UUID() var title: String var date: Date var isDone: Bool var priority: Int } final class TodosStore: ObservableObject { @Published var todos: [Todo] = [] func orderByDate() { todos.sort { $0.date < $1.date } } func orderByPriority() { todos.sort { $0.priority > $1.priority } } func removeCompleted() { todos.removeAll { $0.isDone } } }

Здесь есть класс TodosStore , который соответствует протоколу ObservableObject. TodosStore предоставляет несколько действий для изменения его состояния, мы можем использовать эти методы из наших представлений.

По умолчанию SwiftUI обновляет представление каждый раз, когда изменяется поле @Опубликовано .

Вот почему массив элементов Делать обозначен как @Опубликовано .

Как только мы добавим или удалим элементы из этого массива, SwiftUI обновит представления, на которые подписаны.

TodosStore .

Теперь вы можете создать представление, которое будет отображать список задач и действий, таких как пометка задачи как выполненной, удаление и изменение порядка отображения задач.

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



import SwiftUI struct TodoItemView: View { let todo: Binding<Todo> var body: some View { HStack { Toggle(isOn: todo.isDone) { Text(todo.title.wrappedValue) .

strikethrough(todo.isDone.wrappedValue) } } } }

В приведенном выше примере использовалось Связывание для предоставления ссылки, например доступа к типу значения.

Другими словами, давайте предоставим доступ на запись к элементу todo. Тодоитемвиев не владеет экземпляром структуры Todo, но имеет доступ к записи TodoStore через Связывание .



import SwiftUI struct TodosView: View { @EnvironmentObject var store: TodosStore @State private var draft: String = "" var body: some View { NavigationView { List { TextField("Type something.", text: $draft, onCommit: addTodo) ForEach(store.todos.indexed(), id: \.

1.id) { index, _ in TodoItemView(todo: self.$store.todos[index]) } .

onDelete(perform: delete) .

onMove(perform: move) } .

navigationBarItems(trailing: EditButton()) .

navigationBarTitle("Todos") } } private func delete(_ indexes: IndexSet) { store.todos.remove(atOffsets: indexes) } private func move(_ indexes: IndexSet, to offset: Int) { store.todos.move(fromOffsets: indexes, toOffset: offset) } private func addTodo() { let newTodo = Todo(title: draft, date: Date(), isDone: false, priority: 0) store.todos.insert(newTodo, at: 0) draft = "" } }

Теперь у нас есть ТодосПросмотр - элемент, который использует компонент Список для отображения задач.

Компонент Список также обеспечивает изменение порядка отображения и удаления.

Еще одна интересная вещь — функция индексированный() .

Эта функция возвращает коллекцию элементов с их индексами.

Мы используем его для доступа к элементам в хранилище через Binding. Вот полный исходный код этого расширения.



import Foundation struct IndexedCollection<Base: RandomAccessCollection>: RandomAccessCollection { typealias Index = Base.Index typealias Element = (index: Index, element: Base.Element) let base: Base var startIndex: Index { base.startIndex } var endIndex: Index { base.endIndex } func index(after i: Index) -> Index { base.index(after: i) } func index(before i: Index) -> Index { base.index(before: i) } func index(_ i: Index, offsetBy distance: Int) -> Index { base.index(i, offsetBy: distance) } subscript(position: Index) -> Element { (index: position, element: base[position]) } } extension RandomAccessCollection { func indexed() -> IndexedCollection<Self> { IndexedCollection(base: self) } }

Среда (Среда) — идеальный кандидат для хранения объектов магазина.

Среда может разделить их между несколькими представлениями без явного внедрения через метод. в этом .

Чтобы узнать больше о преимуществах среды в SwiftUI, прочтите статью « Функции среды в SwiftUI “.



Моделирование состояния приложения с использованием объектов хранилища в SwiftUI



Заключение

В этой статье обсуждался способ моделирования состояния приложения с использованием нескольких объектов.

магазин .

Мне очень нравится простота этого подхода и то, насколько легко вы можете масштабировать свое приложение, добавляя больше объектов хранилища.

Надеюсь, вам понравилась эта статья.

Теги: #iOS #разработка iOS #разработка мобильных приложений #программирование #Apple #разработка iOS #Swift #разработка мобильных устройств #xcode #state #swiftUI

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.