The difference between @StateObject, @EnvironmentObject, and @ObservedObject in SwiftUI

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

内容简介:This week I decided to share as much as I can about data flow in SwiftUI. In this post, we will discuss the difference between @SwiftUI uses immutable struct types to describe the view hierarchy. All the views that SwiftUI provides are immutable. That’s wh

This week I decided to share as much as I can about data flow in SwiftUI. In this post, we will discuss the difference between @ StateObject , @ EnvironmentObject , and @ ObservedObject property wrappers. I know that this is the most confusing topic in SwiftUI for newcomers.

Why SwiftUI does need property wrappers?

SwiftUI uses immutable struct types to describe the view hierarchy. All the views that SwiftUI provides are immutable. That’s why SwiftUI gives us a bunch of property wrappers to handle data mutations. Property wrappers allow us to declare them inside SwiftUI views but store the data outside of the view declaring it.

@StateObject

@ StateObject is the new property wrapper that initializes the instance of a class that conforms to ObservableObject protocol and store it inside the SwiftUI framework’s internal memory. SwiftUI creates @ StateObject only once for every container that declares it and keeps it outside of view lifecycle. Let’s look at some examples where we use @ StateObject to keep the whole app’s state.

import SwiftUI

@main
struct CardioBotApp: App {
    @StateObject var store = Store(
        initialState: AppState(),
        reducer: appReducer,
        environment: AppEnvironment(service: HealthService())
    )

    var body: some Scene {
        WindowGroup {
            RootView().environmentObject(store)
        }
    }
}

As you can see, @ StateObject perfectly fits to store the whole app state and share it with different scenes or views of your app. SwiftUI will store it in special framework memory to keep your data in a safe place outside of scene or view lifecycle.

To learn more about using a single state container, take a look at my “Redux-like state container in SwiftUI. Basics.” post.

@EnvironmentObject

@ EnvironmentObject is an excellent way to implicitly inject an instance of a class that conforms to ObservableObject into a part of the view hierarchy. Assume that you have a module in your app that contains 3-4 screens, and all of them use the same ViewModel. If you don’t want to pass the same ViewModel explicitly from one view to another, then @ EnvironmentObject is all you need. Let’s take a look at how we can use it.

import SwiftUI

struct RootView: View {
    @EnvironmentObject var store: Store<AppState, AppAction>

    var body: some View {
        TabView {
            NavigationView {
                SummaryContainerView()
                    .navigationBarTitle("today")
                    .environmentObject(
                        store.derived(
                            deriveState: \.summary,
                            deriveAction: AppAction.summary
                        )
                )
            }.tabItem {
                Image(systemName: "heart.fill")
                    .imageScale(.large)
                Text("today")
            }

            NavigationView {
                TrendsContainerView()
                    .navigationBarTitle("trends")
                    .environmentObject(
                        store.derived(
                            deriveState: \.trends,
                            deriveAction: AppAction.trends
                        )
                )
            }.tabItem {
                Image(systemName: "chevron.up.circle.fill")
                    .imageScale(.large)
                Text("trends")
            }
        }
    }
}

In the example above, we inject the environment object into the view hierarchy of SummaryContainerView . SwiftUI will implicitly give access for inserted environment objects to all child views that live inside SummaryContainerView . We can quickly obtain and subscribe to injected environment objects using @ EnvironmentObject property wrapper.

struct SummaryContainerView: View {
    @EnvironmentObject var store: Store<SummaryState, SummaryAction>

    var body: some View {
        //......
    }
}

To learn more about advanced techniques while using a single state container, take a look at my “Redux-like state container in SwiftUI. Best practices.” post.

@ObservedObject

@ ObservedObject is another way to subscribe and keep track of changes in ObservableObject . Unlike @ EnvironmentObject , you have to make it explicitly. SwiftUI doesn’t control the lifecycle of @ ObservedObject , and you have to manage it yourself. @ ObservedObject perfectly fits a case where you have an ObservableObject stored by @ StateObject , and you want to share it with any reusable view.

struct CalendarContainerView: View {
    @ObservedObject var store: Store<CalendarState, CalendarAction>
    let interval: DateInterval

    var body: some View {
        CalendarView(interval: interval) { date in
            DateView(date: date) {
                self.view(for: date)
            }
        }.navigationBarTitle("calendar", displayMode: .inline)
    }
}

I mention reusable views because I use CalendarContainerView in multiple places in my app, and I don’t want to make it dependent on the environment. I use @ ObservedObject to explicitly indicate the data used by the view in that particular case.

NavigationLink(
    destination: CalendarContainerView(
        store: transformedStore,
        interval: .twelveMonthsAgo
    )
) {
    Text("Calendar")
}

To learn more about using container views, take a look at my “Redux-like state container in SwiftUI. Container Views.” post.

Conclusion

Today we talked about the differences between @ StateObject , @ EnvironmentObject , and @ ObservedObject property wrappers. I hope this post makes it easier to understand which property wrapper fits best your case. Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading, and see you next week!


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

查看所有标签

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

图解密码技术

图解密码技术

[日] 结城浩 / 周自恒 / 人民邮电出版社 / 2014-12 / 79.00元

本书以图配文的形式,详细讲解了6种最重要的密码技术:对称密码、公钥密码、单向散列函数、消息认证码、数字签名和伪随机数生成器。 第一部分讲述了密码技术的历史沿革、对称密码、分组密码模式(包括ECB、CBC、CFB、OFB、CTR)、公钥、混合密码系统。第二部分重点介绍了认证方面的内容,涉及单向散列函数、消息认证码、数字签名、证书等。第三部分讲述了密钥、随机数、PGP、SSL/TLS 以及密码技......一起来看看 《图解密码技术》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具