В чем разница между @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
вместо.