聆听环境变化

时间:2019-07-02 10:56:48

标签: swift swiftui

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

@Environment(\.colorScheme) var colorScheme: ColorScheme

然后根据环境值显示一个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) { }
}

然后在我的body属性中实例化该结构:

var body: some View {
    AppleSignInView(colorScheme: colorScheme)
}

这很好用,但是当我从Xcode更改颜色方案时,不会传播新的颜色方案。

如何聆听此环境变量的更改?

2 个答案:

答案 0 :(得分:3)

这就是我的方法:诀窍是添加.id(self.colorScheme)行。每当colorScheme更改时,这将迫使SwiftUI重绘此按钮。

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

这样可以避免您在if / else语句中返回两个版本的按钮,就像在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) {}
}

答案 1 :(得分:0)

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

看看:https://stackoverflow.com/a/56730649/7786555


更新

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

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) {
    }
}