聆听环境变化

Sud*_*ara 4 swift swiftui

如何检测 SwiftUI 中的环境变化?例如,我将当前的配色方案存储为

@Environment(\.colorScheme) var colorScheme: ColorScheme
Run Code Online (Sandbox Code Playgroud)

ASAuthorizationAppleIDButton根据环境值显示一个:

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) { }
}
Run Code Online (Sandbox Code Playgroud)

在我的body财产中,我实例化了结构:

var body: some View {
    AppleSignInView(colorScheme: colorScheme)
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但是当我从 Xcode 更改配色方案时,新配色方案不会传播。

我如何听取这个环境变量的变化?

Kev*_*ers 5

这是我的做法:诀窍是添加.id(self.colorScheme)行。这会强制 SwiftUI 每次 colorScheme 更改时重新绘制此按钮。

SignInWithAppleButton(style: self.colorScheme == .light ? .black : .white)
  .frame(width: 280, height: 60)
  .onTapGesture(perform: self.showAppleLogin)
  .id(self.colorScheme)
Run Code Online (Sandbox Code Playgroud)

这可以避免在 if/else 语句中返回按钮的 2 个版本,就像在 kontiki 的答案中一样。

还有我的按钮,很好的衡量标准:

struct SignInWithAppleButton: UIViewRepresentable {
  var style: ASAuthorizationAppleIDButton.Style

  func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
    return ASAuthorizationAppleIDButton(type: .default, style: style)
  }

  func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {}
}
Run Code Online (Sandbox Code Playgroud)


kon*_*iki 4

我最近回答了一个类似的问题,OP正在寻找一种使自定义字体对.sizeCategory的环境变化做出反应的方法。

看看:/sf/answers/3971145461/


更新

这是一个有效的实现。请注意,AppleSignInView被放置在 if 语句内。这是为了强制 SwiftUI 重新创建您的UIViewRepresantable。理想情况下,您只需传递 colorScheme,但在这种情况下,您需要更改updateUIView()中的ASAuthorizationAppleIDButton.style。但是,.style 是不可修改的。要解决此问题,您可以使用 if 语句强制重新登录“登录”按钮。

import SwiftUI
import AuthenticationServices

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme: ColorScheme

    var body: some View {

        Group {
            if colorScheme == .light {
                AppleSignInView(colorScheme: .light).frame(width: 200, height: 50)
            } else {
                AppleSignInView(colorScheme: .dark).frame(width: 200, height: 50)
            }
        }
    }
}

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) {
    }
}
Run Code Online (Sandbox Code Playgroud)