На этой неделе я хочу поговорить о моделировании уровней данных в 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 “.
Заключение
В этой статье обсуждался способ моделирования состояния приложения с использованием нескольких объектов.магазин .
Мне очень нравится простота этого подхода и то, насколько легко вы можете масштабировать свое приложение, добавляя больше объектов хранилища.
Надеюсь, вам понравилась эта статья.
Теги: #iOS #разработка iOS #разработка мобильных приложений #программирование #Apple #разработка iOS #Swift #разработка мобильных устройств #xcode #state #swiftUI
-
Waynabox — Рандомное Путешествие За 150 Евро
19 Oct, 24 -
Смерть Одинокого Программиста
19 Oct, 24 -
Мечтают Ли Андроиды О Нирване?
19 Oct, 24 -
Сервисы Быстрой Обратной Связи В Образовании
19 Oct, 24 -
Gphone Появится Через Две Недели
19 Oct, 24