I am using the Observable
macro and when I use @Environment
property wrapper to instance my model the preview stop working. Sample code below
import SwiftUI
import Observation
@Observable class Library {
// ...
}
Now in my main app I created an instance of Library and add that instance to the environment
@main
struct BookReaderApp: App {
@State private var library = Library()
var body: some Scene {
WindowGroup {
LibraryView()
.environment(library)
}
}
}
Now if I want to retrieve the Library instance from any view using the @Environment
property wrapper the preview stop working completely (Assume the BoolView
actually exist)
struct LibraryView: View {
@Environment(Library.self) private var library
var body: some View {
List(library.books) { book in
BookView(book: book)
}
}
}
#Preview {
LibraryView()
}
If I go back and don't use the Observable
macro and just use the ObservableObject
with @StateObject
, .environemntObject
and @EnvironmentObject
the #Preview work fine.
This Observable
macro is "related" new.
Any idea why this is happening? Is there any workaround? I am working with Xcode Version 15.2. Thanks in advance for any kind of help!
When you declare an observable class using @Environment(Type.self)...
, you are implicitly telling the view that the environment object will be present. However, in your preview you're not providing one, and the crash happens when the view tries to access the non-existent object.
There's no need to create a separate EnvironmentKey, as this goes against the ethos of the Observable environment feature. All you need to do is provide an environment copy in your preview.
The following would be sufficient:
#Preview {
LibraryView()
.environment(Library())
}
However, it might be worth creating a dummy example object with values that would demonstrate your view's capabilities, e.g.:
extension Library {
static var example: Library = Library(books: [/* ... */])
}
#Preview {
LibraryView()
.environment(Library.example)
}