Replies: 2 comments 3 replies
-
Hello @MartinP7r, I don't see any problem with modifying multiple environment keys in previews: private struct Service1Key: EnvironmentKey {
static let defaultValue = false
}
private struct Service2Key: EnvironmentKey {
static let defaultValue = false
}
extension EnvironmentValues {
var service1: Bool {
get { self[Service1Key.self] }
set { self[Service1Key.self] = newValue }
}
var service2: Bool {
get { self[Service2Key.self] }
set { self[Service2Key.self] = newValue }
}
}
class MyViewModel: ObservableObject {
let service1: Bool
let service2: Bool
init(service1: Bool, service2: Bool) {
self.service1 = service1
self.service2 = service2
}
}
struct MyView: View {
@EnvironmentStateObject private var viewModel: MyViewModel
init() {
_viewModel = EnvironmentStateObject { env in
MyViewModel(service1: env.service1, service2: env.service2)
}
}
var body: some View {
HStack {
Text(viewModel.service1 ? "1: Custom" : "1: Default")
Spacer()
Text(viewModel.service2 ? "2: Custom" : "2: Default")
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
VStack {
MyView()
MyView()
.environment(\.service1, true)
MyView()
.environment(\.service2, true)
MyView()
.environment(\.service1, true)
.environment(\.service2, true)
}.padding()
}
} |
Beta Was this translation helpful? Give feedback.
-
Thank you for the answer. I see. But I guess the answer to that would inherently be the same. Just initializing all of the nested values in the Preview's environment as well. Let me change your example to illustrate my point: class Service1 {
let isOn: Bool
init(isOn: Bool = false) {
self.isOn = isOn
}
}
class Service2 {
private let service1: Service1
init(service1: Service1 = Service1()) {
self.service1 = service1
}
static let shared = Service2()
var isOn: Bool { service1.isOn }
}
private struct Service1Key: EnvironmentKey {
static let defaultValue = Service1()
}
private struct Service2Key: EnvironmentKey {
static let defaultValue = Service2.shared
}
extension EnvironmentValues {
var service1: Service1 {
get { self[Service1Key.self] }
set { self[Service1Key.self] = newValue }
}
var service2: Service2 {
get { self[Service2Key.self] }
set { self[Service2Key.self] = newValue }
}
}
class MyViewModel: ObservableObject {
let service1: Service1
let service2: Service2
init(service1: Service1, service2: Service2) {
self.service1 = service1
self.service2 = service2
}
}
struct MyView: View {
@EnvironmentStateObject private var viewModel: MyViewModel
init() {
_viewModel = EnvironmentStateObject { env in
MyViewModel(service1: env.service1, service2: env.service2)
}
}
var body: some View {
HStack {
Text(viewModel.service1.isOn ? "1: Custom" : "1: Default")
Spacer()
Text(viewModel.service2.isOn ? "2: Custom" : "2: Default")
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
let service1 = Service1(isOn: true)
let service2 = Service2(service1: service1)
return VStack {
MyView()
MyView()
.environment(\.service1, service1)
MyView()
.environment(\.service2, service2)
MyView()
.environment(\.service1, service1)
.environment(\.service2, service2)
}.padding()
}
} I feel like this wouldn't scale very well with increasing numbers of services. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi @groue 👋🏼 ,
thanks for providing such a well-documented package, as always!
I'm in the process of trying out
@EnvironmentStateObject
on my pet project and ran into some architectural questions.I might be getting something awfully wrong architecture-wise, but here goes:
Consider several layers depending on each other.
Repositories (
PlayerRepository
, ...) depend on the persistence layer (e.g.AppDatabase
in your example app), aMatchService
depending on the repository.Now we have something like
The service is used in a SwiftUI view, let's call it
MatchView
.With a view model initialization:
Env setup
For SwiftUI Previews:
Here the
MatchService
won't be able to get the in-memory database from the environment.Short of having something like
MatchService.preview
or a service (or view model) factory in the environment, I don't see a good pattern that would solve this without too much boiler plate.Do you have any thoughts or ideas on this topic?
Beta Was this translation helpful? Give feedback.
All reactions