Pull to refresh
831.57
OTUS
Цифровые навыки от ведущих экспертов

Новые Property Wrappers в SwiftUI

Reading time 4 min
Views 3.6K
Original author: Majid Jabrayilov

Привет, Хабровчане! В конце августа в OTUS стартует новая группа профессионального базового курса «Разработчик iOS». Как всегда делимся полезным переводом и приглашаем на бесплатные онлайн-мероприятия: «День Открытых Дверей» и «Быстрый старт в IOS-разработку».





WWDC20 привнес в SwiftUI много новых функций, о которых на протяжении следующих недель я собираюсь рассказывать вам в своем блоге. Начать же сегодня я хочу с главных дополнений к потокам данных SwiftUI в виде новых оберток свойств (Property Wrappers) @StateObject, @AppStorage, @SceneStorage и @ScaledMetric.


Если вы не знакомы с существующими обертками свойств, которые предоставляет SwiftUI, я советую вам начать с публикации «Понимаем Property Wrappers в SwiftUI».

StateObject


Как вы помните, SwiftUI предоставляет нам обертку свойства @ObservedObject, которая позволяет нам наблюдать за изменениями в модели данных, которая находится за пределами инфраструктуры SwiftUI. Например, это могут быть данные, которые вы извлекаете из веб-службы или локальной базы данных. Основной проблемой @ObservedObject был жизненный цикл. Вы должны хранить его где-то за пределами SwiftUI, чтобы сохранить его во время обновлений представления, например, в SceneDelegate или AppDelegate. Иначе при определенных обстоятельствах вы можете потерять данные, за которые отвечает @ObservedObject.


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


struct CalendarContainerView: View {
    @StateObject var viewModel = ViewModel()

    var body: some View {
        CalendarView(viewModel.dates)
            .onAppear(perform: viewModel.fetch)
    }
}

AppStorage


AppStorage еще одна новая обертка свойства, которую мы получили в этом году. Это идеальный способ хранения небольшого количества данных вида ключ-значение связанных с UserDefaults. AppStorageDynamicProperty, что означает, что SwiftUI обновит ваши представления, как только значение отдельно взятого ключа обновится в UserDefaults. AppStorage идеально подходит для хранения настроек приложения. Давайте посмотрим, как мы можем ее использовать.


enum Settings {
    static let notifications = "notifications"
    static let sleepGoal = "sleepGoal"
}

struct SettingsView: View {
    @AppStorage(Settings.notifications) var notifications: Bool = false
    @AppStorage(Settings.sleepGoal) var sleepGoal: Double = 8.0

    var body: some View {
        Form {
            Section {
                Toggle("Notifications", isOn: $notifications)
            }

            Section {
                Stepper(value: $sleepGoal, in: 6...12) {
                    Text("Sleep goal is \(sleepGoal, specifier: "%.f") hr")
                }
            }
        }
    }
}

В приведенном выше примере мы создаем экран настроек, используя обертку свойства AppStorage и представление Form. Теперь мы можем получить доступ к нашим настройкам в любом месте приложения с помощью AppStorage, и как только мы изменим там какие-либо значения, SwiftUI обновит представления.


struct ContentView: View {
    @AppStorage(Settings.sleepGoal) var sleepGoal = 8
    @StateObject var store = SleepStore()

    var body: some View {
        WeeklySleepChart(store.sleeps, goal: sleepGoal)
            .onAppear(perform: store.fetch)
    }
}

SceneStorage


В этом году мы получили множество возможностей для управления сценами в SwiftUI без UIKit. В результате у нас появилась новая обертка свойства SceneStorage, которая позволяет нам реализовать правильное восстановление состояния для наших сцен. SceneStorage работает аналогично AppStorage, но вместо UserDefaults использует отдельное хранилище для каждой сцены. Это означает, что каждая сцена имеет свое собственное хранилище, к которому не могут получить доступ другие сцены. Система полностью отвечает за управление хранилищем для каждой сцены, и у вас нет доступа к данным без обертки свойства SceneStorage.


struct ContentView: View {
    @SceneStorage("selectedTab") var selection = 0

    var body: some View {
        TabView(selection: $selection) {
            Text("Tab 1").tag(0)
            Text("Tab 2").tag(1)
        }
    }
}

Я рекомендую использовать SceneStorage для хранения специфичных для сцены данных, таких как набор вкладок или индекс выбранной книги, в приложении для чтения. В настоящее время iOS очень агрессивна с точки зрения уничтожения приложений в фоновом режиме, и восстановление состояния является ключевым решением для обеспечения положительного юзер экспириенса.


ScaledMetric


Еще одна новая обертка свойства — ScaledMetric. ScaledMetric позволяет нам масштабировать любое двоичное плавающее значение относительно категории размера Dynamic Type. Например, в вашем приложении можно очень легко изменить интервалы в соответствии с категорией размера Dynamic Type. Давайте посмотрим на небольшой пример.


struct ContentView: View {
    @ScaledMetric(relativeTo: .body) var spacing: CGFloat = 8

    var body: some View {
        VStack(spacing: spacing) {
            ForEach(0...10, id: \.self) { number in
                Text(String(number))
            }
        }
    }
}

Как только пользователь изменит настройки Dynamic Type, SwiftUI масштабирует значение интервала и обновит представление.


Заключение


Сегодня мы узнали о новых обертках свойств в SwiftUI. Я считаю, что теперь мы имеем достаточно оберток свойств потоков данных, чтобы охватить любую логику, которая нам потребуется при реализации наших приложений. Не стесняйтесь подписываться на меня в Twitter и задавать свои вопросы, связанные с этой статьей. Спасибо за внимание и хорошей вам недели!




Узнать подробнее о базовом курсе «Разработчик iOS»



Tags:
Hubs:
+3
Comments 0
Comments Leave a comment

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS