Unexpected sharing of overrides in SwiftUI Preview traits #322
-
Hello there! import Dependencies
import IssueReporting
import Foundation
import SwiftUI
struct SampleClient {
var func1: @Sendable () throws -> String
var func2: @Sendable () throws -> String
}
extension SampleClient: DependencyKey {
static let liveValue = SampleClient(
func1: { "LiveFunc1" },
func2: { "LiveFunc2" }
)
static let previewValue: SampleClient = SampleClient(
func1: { "MockFunc1" },
func2: { "MockFunc2" }
)
static let testValue: SampleClient = SampleClient(
func1: IssueReporting.unimplemented("UnimplementedFunc1"),
func2: IssueReporting.unimplemented("UnimplementedFunc2")
)
}
extension DependencyValues {
var sampleClient: SampleClient {
get { self[SampleClient.self] }
set { self[SampleClient.self] = newValue }
}
}
struct ContentView: View {
@Dependency(\.sampleClient) var sampleClient
var body: some View {
VStack {
Text(try! self.sampleClient.func1())
.font(.system(size: 50))
Text(try! self.sampleClient.func2())
.font(.system(size: 50))
}
}
}
@available(iOS 18, *)
#Preview(
"Preview1",
traits: .dependencies {
$0.sampleClient.func1 = { @Sendable in "Preview1" }
}
) {
ContentView()
}
@available(iOS 18, *)
#Preview(
"Preview2",
traits: .dependencies {
$0.sampleClient.func2 = { @Sendable in "Preview2" }
}
) {
ContentView()
} I always get this result for both previews: Is this expected behavior? I would expect the previews to show this instead:
@mbrandonw @stephencelis Why are the dependency overrides being shared between Previews? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
@cabeca This is a quirk/bug of Xcode previews. If you have multiple defined in a single file, they will all execute even though you're only viewing a single one. You should be able to reproduce this in a vanilla project, so we think it's worth filing feedback if you find the behavior surprising. Preview traits only provide a "modifier" extension to apply to a view after it's been computed, which we can't leverage, so instead our trait is simply a shorthand for So for now, we recommend one of the following workarounds:
|
Beta Was this translation helpful? Give feedback.
@cabeca This is a quirk/bug of Xcode previews. If you have multiple defined in a single file, they will all execute even though you're only viewing a single one. You should be able to reproduce this in a vanilla project, so we think it's worth filing feedback if you find the behavior surprising.
Preview traits only provide a "modifier" extension to apply to a view after it's been computed, which we can't leverage, so instead our trait is simply a shorthand for
prepareDependencies
, which globally overrides dependencies for the process. This global is going to bleed over to other previews defined in the same file as a result. We're open to ideas on how to improve this, but we're not sure it…