Reputation: 399
I have a variable named homesList
that I set in the completion handler of a function call to the server. However, homesList
is not accessible in the PreviewProvider
. How can I access homesList
in the PreviewProvider?
struct HomeRow: View {
var home: Home
@State private var homesList: [Home]
var body: some View {
HStack {
Text(home.homeName)
Spacer()
}
.onAppear {
retrieveHomes(completionHandler: { (json) in
self.homesList = json
})
}
}
}
struct HomeRow_Previews: PreviewProvider {
static var previews: some View {
Group {
HomeRow(home: homesList[0])
}
.previewLayout(.fixed(width: 300, height: 70))
}
}
Upvotes: 1
Views: 571
Reputation: 257779
Separating model management into view model and using dependency injection give possibility to mock view model for preview.
Here is a demo of possible approach. Tested with Xcode 12 / iOS 14
struct Home { // just replicated for test
var homeName: String
}
class HomesViewModel: ObservableObject {
@Published var homesList: [Home]
init(homes: [Home] = []) { // default container
self.homesList = homes
}
func fetchHomes() {
guard homesList.isEmpty else { return }
retrieveHomes(completionHandler: { (json) in // load if needed
DispatchQueue.main.async {
self.homesList = json // should be set on main queue
}
})
}
}
struct HomeRow: View {
var home: Home
@ObservedObject var vm: HomesViewModel
var body: some View {
HStack {
Text(home.homeName)
Spacer()
}
.onAppear {
self.vm.fetchHomes()
}
}
}
struct HomeRow_Previews: PreviewProvider {
static var previews: some View {
// prepare mock model with predefined mock homes
let mockModel = HomesViewModel(homes: [Home(homeName: "Mock1"), Home(homeName: "Mock2")])
return Group {
// inject test model via init
HomeRow(home: mockModel.homesList[0], vm: mockModel)
}
.previewLayout(.fixed(width: 300, height: 70))
}
}
Upvotes: 1