How to set an Environment Object in preview
You add it using .environmentObject(_:) modifier:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(YourObject())
}
}
Modifying environment object for previews?
Here is possible approach
static var previews: some View {
Group {
SomeView().environmentObject({ () -> AuthenticationViewModel in
let v = AuthenticationViewModel()
v.showResendCodeTimer = true
return v
}())
SomeView().environmentObject({ () -> AuthenticationViewModel in
let v = AuthenticationViewModel()
v.showResendCodeTimer = false
return v
}())
}
}
SwiftUI - Mocking @EnvironmentObject data in preview
Assuming the UserService
has correctly designed using dependency injection, it can be used the following approach with any explicit changes in production code
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
let userService = UserService()
userService.user = User(username: "Alex", email: "alex@test.com") // << any predefined set up here
// any more parameters set up here
return WelcomeView().environmentObject(userService)
}
}
How to solve this problem of environment object ?
Your sample code is missing some lines at the start of the view. By the sounds of the error message, you already have something like:
struct MyView: View {
@EnvironmentObject var appData: AppData
// ...rest of view ...
}
Alongside that code to get a reference for your object out of the environment, you also need to ensure that, somewhere further up the chain, it's put in. Your error message is telling you that that is where the problem lies – it's looking in the environment for a type of AppData
object, but there's nothing in there.
Let's say you declare it the app level; it might look something like this:
@main
struct TestDemoApp: App {
// 1. Instantiate the object, using `@StateObejct` to make sure it's "owned" by the view
@StateObject var appData = AppData()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(appData) // 2. make it available to the hierarchy of views
}
}
}
What you'll also have to do is make sure that any views that use your environment object also have access to one in their Xcode previews. You might want to create a version of AppData
that has example data inside so that your previews don't mess with live data.
extension AppData {
static var preview: AppData = ...
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(AppData.preview)
}
}
PreviewProvider and ObservedObject properties
If you are using the standard PersistenceController
that comes with Xcode when you start a new project with CoreData just add the below method so Xcode returns the .preview
container
when you are running in preview.
public static func previewAware() -> PersistenceController{
//Identifies if XCode is running for previews
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"{
return PersistenceController.preview
}else{
return PersistenceController.shared
}
}
As for the rest you can use something like this.
import SwiftUI
import CoreData
struct SamplePreviewView: View {
@ObservedObject var item: Item
var body: some View {
Text(item.timestamp?.description ?? "nil")
}
}
struct SamplePreviewView_Previews: PreviewProvider {
static let svc = CoreDataPersistenceService()
static var previews: some View {
SamplePreviewView(item: svc.addSample())
}
}
class CoreDataPersistenceService: NSObject {
var persistenceController: PersistenceController
init(isTest: Bool = false) {
if isTest{
self.persistenceController = PersistenceController.preview
}else{
self.persistenceController = PersistenceController.previewAware()
}
super.init()
}
func addSample() -> Item {
let object = createObject()
object.timestamp = Date()
return object
}
//MARK: CRUD methods
func createObject() -> Item {
let result = Item.init(context: persistenceController.container.viewContext)
return result
}
}
Related Topics
Wrapping a Generic Method in a Class Extension
Firebasefirestoreswift Won't Install (Cocoapods)
How to Draw a Cosine or Sine Curve in Swift
Swift 2.0 'Inout' Function Parameters and Computed Properties
Extension for Generic Type 'Unsafemutablepointer<Uint8>'
Why Is It Legal to Mutate an Actor's Nonsendable Property
How to Draw a Line Between Two Points in Scenekit
What's the Best Way to Iterate Over Results from an API, and Know When It's Finished
Incorrect String to Date Conversion Swift 3.0
Add Skreferencenode/Skscene to Another Skscene in Spritekit
Swift Encode Tuple Using Nscoding
How to Implement iOServicematchingcallback in Swift
How to Rotate Sprites Around a Joint
Cannot Add Alamofire to Swift Project
In Swift, Does Int Have a Hidden Initializer That Takes a String
How to Loop Through an Array from the Second Element in Elegant Way Using Swift