UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to use environment objects in Preview

Forums > SwiftUI

Hello,

I am trying to setup the preview for my view like this:

import SwiftUI

struct BoardConfigView: View {

    // Position
    @EnvironmentObject var position: Position

    // Board
    @EnvironmentObject var board: Board

    var body: some View {
        VStack {
            ...
        }
        .padding()
    }

    func setWhiteColor() {
        board.whiteColor = .yellow
    }

    func setBlackColor() {
        board.whiteColor = .red
    }
}

#Preview {
    var position = Position()
    var board = Board()
    BoardConfigView()
        .environmentObject(position)
        .environmentObject(board)
}

However I then see this warning: Result of call to 'environmentObject' is unused

I also tried this:

#Preview {
    BoardConfigView(position: Position(), board: Board())
}

Resulting in the following errors:

Cannot convert value of type 'Board' to expected argument type 'EnvironmentObject<Board>' and Cannot convert value of type 'Position' to expected argument type 'EnvironmentObject<Position>'

Please can someone:

(1) give me the correct syntax (2) explain why it is that calling the memberwise initializer is wrong? My understanding is that with no defined initializer Swift synthesizes a default memberwise initializer so why does the first version that calls the (non-existent???) no argument initialier not show as an error?

Thank you

   

Put return before BoardConfigView

#Preview {
    var position = Position()
    var board = Board()
    return BoardConfigView()
                  .environmentObject(position)
                  .environmentObject(board)
}

or

#Preview {
    BoardConfigView()
        .environmentObject(Position())
        .environmentObject(Board())
}

   

Thank you @NigelGee that did solve the problem. But please can someone also explain why it is not necessary to call the memberwise initializer to create the view in this case?

For structs generally unless you define your own initializer there is a single memberwise initializer synthesized by the compiler so there should not be a no-argument initializer like that used in the above code in #Preview so this appears to break the rule that all non-optional properties are initialized by the time the initializer completes ??

   

Well #Preview is a macro that if you Ctl+click and select Expand Macro you will see that it is a struct that has a static func makePreview() that returns DeveloperToolsSupport.Preview and in the closure there is a

DeveloperToolsSupport.Preview {
// some code
}

The some code is what you put in the preview, however when you put properties you need to return the DeveloperToolsSupport.Preview (which is a View I think).

It a bit like

func makeText() -> String {
    "TEXT"
}

however if you add a property like you need to return something

func makeText() -> String {
    let text = "TEXT"
    return text
}

if you asking why the following works is that as previews do hold anything you just creating an instant of them for it.

.environmentObject(Position())
.environmentObject(Board())

   

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.