How do I detect environment changes in SwiftUI? For example, I store the current colour scheme as
@Environment(\.colorScheme) var colorScheme: ColorScheme
And I display an ASAuthorizationAppleIDButton
based on the environment value:
fileprivate struct AppleSignInView : UIViewRepresentable {
var colorScheme: ColorScheme
func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
switch colorScheme {
case .light:
return ASAuthorizationAppleIDButton(type: .continue, style: .black)
case .dark:
return ASAuthorizationAppleIDButton(type: .continue, style: .white)
@unknown default:
return ASAuthorizationAppleIDButton(type: .continue, style: .black)
}
}
func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) { }
}
And In my body
property I instantiate the struct:
var body: some View {
AppleSignInView(colorScheme: colorScheme)
}
This works fine, but the new colour scheme isn't propagated when I change the colour scheme from the Xcode.
How do I listen to this environment variable change?
Here is how I do it: the trick is to add the .id(self.colorScheme)
line. This forces SwiftUI to redraw this button every time the colorScheme changes.
SignInWithAppleButton(style: self.colorScheme == .light ? .black : .white)
.frame(width: 280, height: 60)
.onTapGesture(perform: self.showAppleLogin)
.id(self.colorScheme)
This saves you from returning 2 versions of the button in an if/else statement, like in kontiki's answer.
And my button, for good measure:
struct SignInWithAppleButton: UIViewRepresentable {
var style: ASAuthorizationAppleIDButton.Style
func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
return ASAuthorizationAppleIDButton(type: .default, style: style)
}
func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With