iTranslated by AI
Managing ObservableObject in SwiftUI
To make data observable in SwiftUI, create an object that conforms to the ObservableObject protocol.
class Book: ObservableObject {
@Published var title = "Great Expectations"
}
Three methods are provided for making an object conforming to ObservableObject an observation target from SwiftUI.
- StateObject (iOS14+)
- ObservedObject
- EnvironmentObject
StateObject
StateObject behaves by creating and managing a single instance for a View. Therefore, it is suitable for managing data (models) used throughout the entire application.
@main
struct BookReader: App {
@StateObject var library = Library()
var body: some Scene {
WindowGroup {
...
}
}
}
ObservedObject
Unlike StateObject, ObservedObject manages instances in accordance with the View's lifecycle. If you create an instance using ObservedObject, there is a possibility of side effects where data is lost when the View is recreated. Furthermore, because an instance is created every time the View is generated, the overhead can become large. It is better to use ObservedObject for the purpose of referencing instances passed from parent Views or other sources, rather than for creating instances.
struct LibraryView: View {
@StateObject var book = Book()
var body: some View {
BookView(book: book)
}
}
struct BookView: View {
@ObservedObject var book: Book
var body: some View {
BookEditView(book: book)
}
}
struct BookEditView: View {
@ObservedObject var book: Book
// ...
}
EnvironmentObject
EnvironmentObject allows access to instances passed from a higher-level View in the hierarchy using environmentObject(). Unlike ObservedObject, it can be received by views that are not direct parents, eliminating the need to pass instances down through multiple levels (prop drilling). This is useful when you want to share an object used across the entire app with many views or deeply nested child views.
@main
struct BookReader: App {
@StateObject var library = Library()
var body: some Scene {
WindowGroup {
LibraryView()
.environmentObject(library)
}
}
}
struct LibraryView: View {
@EnvironmentObject var library: Library
// ...
}
How should they be used?
It is recommended to create instances using StateObject and use ObservedObject or EnvironmentObject when referencing those instances.
- Use
StateObjectwhen creating instances inApp, Scene, or View.- Objects can be managed independently of the View's lifecycle.
- Use
ObservedObjectwhen receiving instances from aparent View.- Object creation and destruction are tied to the View's lifecycle.
- Use
EnvironmentObjectwhen instances are passed viaenvironmentObject.- Instances declared at the top level of the app can be referenced from all views.
References
Managing Model Data in Your App
Discussion