В чем разница между @EnvironmentObject и @ObservedObject?

Я читал об оболочках свойств в SwiftUI и вижу, что они отлично справляются со своей задачей, но я действительно не понимаю разницы между @EnvironmentObject и @ObservedObject.

Из того, что я узнал до сих пор, я вижу, что @EnvironmentObject используется, когда у нас есть объект, который нужен в разных местах нашего приложения, но нам не нужно передавать его через все из них. Например, если у нас есть иерархия A -> B -> C -> D и объект создается в A, он сохраняется в среде, чтобы мы могли передать его напрямую от A к D, если это необходимо D.

Если мы используем @ObservedObject, который создается в A и должен быть передан в D, тогда нам также нужно пройти через B и C.

Но я все еще не знаю, как решить, какой использовать. Вот 2 примера проектов, которые я сделал:

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

а также

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

Оба кода выполняют одно и то же обновление представления. Также оба ContentView передают объект Order. Разница в том, что Environment передает .environmentObject (order), а Observed передает его напрямую EditView (order: order). Для меня оба выполняют одну и ту же работу, только их декларация отличается, поэтому я был бы признателен за некоторые объяснения или лучший пример.

1 ответ

Решение

Как вы заметили @ObservedObjectнужно передавать из поля зрения в поле зрения. Может быть лучше для простой иерархии представлений, когда у вас не слишком много представлений.


Предположим, у вас есть следующая иерархия:

ViewA -> ViewB -> ViewC -> ViewD

Теперь, если ты хочешь @ObservedObject от ViewA быть в ViewB нет проблем с передачей его прямо в init.

Но что, если вы хотите ViewDтакже? А что делать, если вViewB а также ViewC?

С @ObservedObject вам нужно будет вручную передать его из ViewA к ViewB а затем в ViewC, а затем в ViewD. И вам нужно будет объявить его в каждом дочернем представлении.

С @EnvironmentObject это просто - просто передайте его в представление верхнего уровня:

ViewA().environmentObject(someObservableObject)

Затем вы объявляете его только в том представлении, которое его использует - это может сделать ваш код более читабельным.


Заметка

Каждый объект в среде (иерархия представлений) может получить доступ к введенному@EnvironmentObject. Если вы этого не хотите (конфиденциальность важна), вам может потребоваться передать его как@ObservedObject вместо.

Другие вопросы по тегам