How to Set an Environment Object in Preview

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



Leave a reply



Submit