简体   繁体   English

如何在 SwiftUI 中使用 Toogle 禁用 TextField?

[英]How to disable TextField with Toogle in SwiftUI?

How should TextField be properly disabled when using Toogle in swiftUI?在 swiftUI 中使用 Toogle 时应该如何正确禁用 TextField? The following simple example causes warnings in the console if we disable a TextField that has some value entered in it, deleting it doesn't fix the situation either.如果我们禁用其中输入了某些值的 TextField,以下简单示例会在控制台中引起警告,删除它也不能解决问题。

struct ContentView: View {
@State var isToogleOn = false
@State var textFieldValue = ""

var body: some View {
    HStack {
        TextField("Placeholder", text: $textFieldValue)
            .disabled(!isToogleOn)
        Toggle("Activate textField", isOn: $isToogleOn)
        }
    }
}

Warnings when textfield is switched off:关闭文本字段时的警告:

=== AttributeGraph: cycle detected through attribute 160396 === 2022-01-08 15:27:46.182588+0100 CrochetIo[15460:1558507] [SwiftUI] Modifying state during view update, this will cause undefined behavior === AttributeGraph:通过属性 160396 检测到循环 === 2022-01-08 15:27:46.182588+0100 CrochetIo[15460:1558507] [SwiftUI] 在视图更新期间修改 state,这将导致未定义的行为

Actually it is Apple's logs, so we should not care about them, but if they disturb you, then it is possible to solve that, because they are posted due to TextField is still in focus during disable.实际上是苹果的日志,所以我们不应该关心它们,但是如果它们打扰到你,那么有可能解决这个问题,因为它们被发布是因为TextField在禁用期间仍然处于焦点。

The possible approach is to use proxy binding on toggle with injected pre-set side-effect.可能的方法是在切换时使用代理绑定并注入预设的副作用。

Tested with Xcode 13.2 / iOS 15.2使用 Xcode 13.2 / iOS 15.2 测试

struct ContentViewTestToggleText: View {
    @State var isToogleOn = false
    @State var textFieldValue = ""

    var body: some View {
        HStack {
            TextField("Placeholder", text: $textFieldValue)
                .disabled(!isToogleOn)

            let onToggle = Binding(
                get: { self.isToogleOn },
                set: {
                    if !$0 {
                        UIApplication.shared.endEditing()     // << here !!
                    }
                    
                    self.isToogleOn = $0
                }
            )
            Toggle("Activate textField", isOn: onToggle)
        }
    }
}

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

The reason given by @Asperi is correct, but I would suggest other solution. @Asperi 给出的原因是正确的,但我会建议其他解决方案。 When switching Toogle off, let's drop the focus on the TextField and only then disable it.关闭Toogle时,让我们将焦点放在TextField上,然后才将其禁用。

    @State var isToogleOn = false
    @State var textFieldIsDisabled = false
    @State var textFieldValue = ""
    
    @FocusState private var focusField: Field?
    
    var body: some View {
        HStack {
            TextField("Placeholde", text: $textFieldValue)
                .focused($focusField, equals: .textField1)
                .disabled(textFieldIsDisabled)
            Toggle("Activate textField", isOn: $isToogleOn)
                .onChange(of: isToogleOn) { newValue in
                    focusField = nil
                    textFieldIsDisabled = !newValue
                }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM