New property wrappers in SwiftUI

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

内容简介: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!


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

查看所有标签

猜你喜欢:

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

Alone Together

Alone Together

Sherry Turkle / Basic Books / 2011-1-11 / USD 28.95

Consider Facebookit’s human contact, only easier to engage with and easier to avoid. Developing technology promises closeness. Sometimes it delivers, but much of our modern life leaves us less connect......一起来看看 《Alone Together》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具