【问题标题】:Listen for Environment Changes聆听环境变化
【发布时间】:2019-07-02 10:56:48
【问题描述】:

如何在 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 更改配色方案时,新的配色方案不会传播。

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

【问题讨论】:

  • 做 bata-binding 可能有帮助....

标签: swift swiftui


【解决方案1】:

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

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

这可以避免您在 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) {}
}

【讨论】:

    【解决方案2】:

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

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


    更新

    这是一个有效的实现。请注意,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) {
        }
    }
    

    【讨论】:

    • 另请注意,当前 beta 2 中的暗/亮模式似乎存在许多错误。
    • 更新了我的答案以包含一个可行的解决方案。在模拟器上测试并从“设置”应用更改了配色方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    相关资源
    最近更新 更多