New property wrappers in SwiftUI

栏目: IT技术 · 发布时间: 3年前

内容简介:WWDC20 brought a lot of new features into SwiftUI that I will discuss on my blog during the next weeks. Today I would like to start with the main additions to SwiftUI data flow with the brand new @If you are not familiar with the legacy property wrappers t

WWDC20 brought a lot of new features into SwiftUI that I will discuss on my blog during the next weeks. Today I would like to start with the main additions to SwiftUI data flow with the brand new @ StateObject , @ AppStorage , @ SceneStorage , and @ ScaledMetric property wrappers.

If you are not familiar with the legacy property wrappers that SwiftUI provides, I suggest to start with my “Understanding Property Wrappers in SwiftUI” post.

StateObject

As you remember, SwiftUI provides us the @ ObservedObject property wrapper that allows us to observe the changes in the data model that lives outside of the SwiftUI framework. For example, it might be the data that you fetch from web service or the local database. The main concern about @ ObservedObject was the lifecycle. You have to store it somewhere outside of SwiftUI to save it during view updates, for example, in SceneDelegate or AppDelegate . In other cases, you can lose the data backed by @ ObservedObject in certain circumstances.

Here is the brand new StateObject property wrapper that fills the most significant gap in SwiftUI data flow management. SwiftUI creates only one instance of the StateObject for each container instance that you declare and holds it in the internal framework memory that saves it during view updates. StateObject works in a very similar way to State property wrapper, but instead of value types, it is designed to work with reference types.

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

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

AppStorage

AppStorage is another new property wrapper that we have this year. It is a perfect way to store a small amount of key-value data backed by UserDefaults . AppStorage is DynamicProperty , which means SwiftUI will update your views as soon as the value of a particular key in UserDefaults will update. AppStorage perfectly fits to store app settings. Let’s take a look at how we can use it.

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")
                }
            }
        }
    }
}

In the example above, we build a settings screen using the AppStorage property wrapper and Form view. Now we can access our settings anywhere across the app using AppStorage , and as soon as we change the values, SwiftUI will update the views.

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

This year we got all the abilities to control scenes in SwiftUI without UIKit. As a result, we have a new SceneStorage property wrapper that allows us to implement proper state restoration for our scenes. SceneStorage works similarly to AppStorage , but instead of UserDefaults , it uses per-scene storage. It means every scene has its private storage that can’t be accessed by other scenes. The system entirely responsible for managing per-scene storage, and you don’t have access to the data without SceneStorage property wrapper.

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)
        }
    }
}

I recommend using SceneStorage to store scene-specific data like tab selection or selected book index in a reader app. Nowadays, iOS is very aggressive in terms of killing apps in the background, and state restoration is the key solution to provide a great user experience.

ScaledMetric

Another brand new property wrapper that we have is ScaledMetric . ScaledMetric allows us to scale any binary floating value relative to the Dynamic Type size category. For example, it is so easy to change the spacing in your app according to the Dynamic Type size category. Let’s take a look at the small example.

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))
            }
        }
    }
}

As soon as user changes the Dynamic Type settings, SwiftUI scales the value of spacing and update the view.

Conclusion

Today we learned about new property wrappers in SwiftUI. I believe there are enough data flow property wrappers that can cover any logic we need while implementing our apps. Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading, and have a nice week!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ES6 标准入门(第2版)

ES6 标准入门(第2版)

阮一峰 / 电子工业出版社 / 2016-1 / 69.00元

ES6(又名 ES2105)是 JavaScript 语言的新标准,2015 年 6 月正式发布后,得到了迅速推广,是目前业界超级活跃的计算机语言。《ES6标准入门(第2版)》是国内仅有的一本 ES6 教程,在前版基础上增补了大量内容——对标准进行了彻底的解读,所有新增的语法知识(包括即将发布的 ES7)都给予了详细介绍,并且紧扣业界开发实践,给出了大量简洁易懂、可以即学即用的示例代码。 《......一起来看看 《ES6 标准入门(第2版)》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具