What is the difference between @EnvironmentObject and @ObservedObject?

扶醉桌前 提交于 2021-02-08 15:12:37

问题


I have been reading about the property wrappers in SwiftUI and I see that they do a great job, but one thing which I really don't get is the difference between @EnvironmentObject and @ObservedObject.

From what I learned so far, I see that @EnvironmentObject is used when we have an object that is needed in various places in our app but we don't need to pass it through all of them. For example if we have hierarchy A -> B -> C -> D and the object is created at A, it is saved in the environment so that we can pass it directly from A to D, if D needs it.

If we use @ObservedObject which is created at A and needs to be passed to D, then we need to go through B and C as well.

But I still don't know how to decide which one to use. Here are 2 example projects which I made:

struct ContentView2: View {
 
   var order = Order2()

   var body: some View {
      VStack {
           EditView2()
           DisplayView2()
       }
       .environmentObject(order)
   }
}
struct EditView2: View {
   @EnvironmentObject var user: Order2
 
   var body: some View {
       HStack{
       TextField("Fruit", text: $user.item)
       }
   }
}
struct DisplayView2: View {
   @EnvironmentObject var user: Order2
   var body: some View {
       VStack{
       Text(user.item)
       }
   }
}
class Order2: ObservableObject {
       @Published var item = "Orange"
   }

and

struct ContentView: View {

    var order = Order()
    
    var body: some View {
       VStack {
            EditView(order: order)
            DisplayView(order: order)
        }
    }
}
struct EditView: View {
    @ObservedObject var order: Order
    var body: some View {
        HStack{
        TextField("Fruit", text: $order.item)
        }
    }
}
struct DisplayView: View {
      @ObservedObject var order: Order
      var body: some View {
        VStack{
        Text(order.item)
        }
    }
}
class Order: ObservableObject {
    @Published var item = "Apple"
}

Both codes do the same update of the view. Also both ContentViews, pass an Order object. The difference is that Environment passes .environmentObject(order) and Observed passes it directly EditView(order: order). For me, both do same job, only their declaration is different, therefore I would appreciate some explanation or a better example.


回答1:


As you've noticed an @ObservedObject needs to be passed from view to view. It may be better for a simple view hierarchy when you don't have too many views.


Let's assume you have the following hierarchy:

ViewA -> ViewB -> ViewC -> ViewD

Now if you want your @ObservedObject from the ViewA to be in the ViewB there's no problem with passing it directly in init.

But what if you want it in the ViewD as well? And what if you don't need it in the ViewB and ViewC?

With an @ObservedObject you'd need to manually pass it from the ViewA to the ViewB and then to the ViewC, and then to the ViewD. And you'd need to declare it in every child view.

With an @EnvironmentObject it's easy - just pass it to the top-level view:

ViewA().environmentObject(someObservableObject)

Then you only declare it in the view that uses it - this may make your code more readable.


Note

Every object in the environment (view hierarchy) can access the injected @EnvironmentObject. If you don't want this (privacy is important) you may need to pass it as an @ObservedObject instead.



来源:https://stackoverflow.com/questions/63343819/what-is-the-difference-between-environmentobject-and-observedobject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!