Missives and musings on a variety of topics.

SwiftUI Previews: How to fix 'Cannot convert value of type SomeType to expected argument type EnvironmentObject' errors

Using @EnvironmentObject is a great way to share data between your views. Previously, I'd been using @ObservedObjects all over my views, and it felt clumsy.

Hot tip: by setting an environmentObject for a NavigationView, any children of this NavigationView can then add a property like @EnvironmentObject var someType: SomeType. SwiftUI then gives them access to the observed object, without you having to pass the object down the navigation tree and through views that don't need access to it:

/* ContentView.swift */

import SwiftUI

struct ContentView: View {
    @ObservedObject var someType: SomeType

    var body: some View {
        NavigationView {
            MyView()
        }
        .environmentObject(someType)
    }
}

/* MyView.swift */

import SwiftUI

struct MyView: View {
    var body: some View {
        SomeTypeList()
    }
}


/* SomeTypeList.swift */

import SwiftUI

struct SomeTypeList: View {
    @EnvironmentObject var someType: SomeType
    
    var body: some View {
        // Do something with someType
    }
}

But! If you were passing it in to a child view as an ObservedObject and had set up some test object for use in your SwiftUI preview? If you try to pass in your test object, you'll get an error:

Cannot convert value of type 'SomeType' to expected argument type 'EnvironmentObject<SomeType>'

To fix this, use the environmentObject modifier on your child view's preview provider:

struct SomeTypeList_Previews: PreviewProvider {
    static var previews: some View {
        SomeTypeList()
            .environmentObject(testSomeType)
    }
}

Yay, your preview works again!

#swift #swiftui

Discuss...