Что такое property wrapper @ObservedObject в SwiftUI?

«Что такое property wrapper @ObservedObject в SwiftUI?» — вопрос из категории SwiftUI, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

@ObservedObject — это property wrapper в SwiftUI, который создает подписку представления (View) на изменения внешнего объекта, соответствующего протоколу ObservableObject.

Основная роль:

Он сообщает SwiftUI: "Эта View зависит от данных из внешнего объекта. Перерисуй меня, когда его @Published свойства изменятся".

Пример и сравнение с @StateObject:

class DataModel: ObservableObject {
    @Published var value = 0
}

struct ParentView: View {
    // @StateObject — для СОЗДАНИЯ и ВЛАДЕНИЯ объектом.
    // SwiftUI управляет его жизненным циклом и не уничтожает при перерисовке ParentView.
    @StateObject private var myModel = DataModel()

    var body: some View {
        VStack {
            Text("Родитель: (myModel.value)")

            // @ObservedObject — для ПЕРЕДАЧИ уже существующего объекта в дочернюю View.
            // Дочерняя View подписывается на его изменения, но не владеет им.
            ChildView(observedModel: myModel)
        }
    }
}

struct ChildView: View {
    // Получаем объект извне и подписываемся на его изменения.
    @ObservedObject var observedModel: DataModel

    var body: some View {
        Button("Увеличить в дочерней") {
            observedModel.value += 1 // Изменение обновит и ParentView, и ChildView
        }
    }
}

Ключевые правила использования:

  1. Для внешних зависимостей: Используйте @ObservedObject, когда объект создается и управляется за пределами текущей View (например, передан из родительской View или через @EnvironmentObject).
  2. Не является источником истины: @ObservedObject не создает и не хранит объект. Он только создает на него подписку. Если источник данных (родительская View) перестанет существовать, объект может быть деинициализирован.
  3. Для создания и владения объектом внутри View всегда используйте @StateObject. Это предотвращает неожиданное воссоздание объекта при перерисовке View.