如何在 SwiftUI 中禁用带有切换的文本字段?
How to disable TextField with Toogle in SwiftUI?
在swiftUI中使用Toogle时应该如何正确禁用TextField?如果我们禁用其中输入了一些值的 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)
}
}
}
关闭文本框时的警告:
=== 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
其实是Apple的日志,所以我们不应该关心它们,但是如果它们打扰了你,那么可以解决,因为它们是由于TextField
在禁用期间仍然处于焦点状态而发布的.
可能的方法是在带有注入的预设副作用的切换上使用代理绑定。
测试 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 ![=10=] {
UIApplication.shared.endEditing() // << here !!
}
self.isToogleOn = [=10=]
}
)
Toggle("Activate textField", isOn: onToggle)
}
}
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
@Asperi 给出的理由是正确的,但我会建议其他解决方案。当关闭 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
}
}
}
}
在swiftUI中使用Toogle时应该如何正确禁用TextField?如果我们禁用其中输入了一些值的 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)
}
}
}
关闭文本框时的警告:
=== 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
其实是Apple的日志,所以我们不应该关心它们,但是如果它们打扰了你,那么可以解决,因为它们是由于TextField
在禁用期间仍然处于焦点状态而发布的.
可能的方法是在带有注入的预设副作用的切换上使用代理绑定。
测试 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 ![=10=] {
UIApplication.shared.endEditing() // << here !!
}
self.isToogleOn = [=10=]
}
)
Toggle("Activate textField", isOn: onToggle)
}
}
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
@Asperi 给出的理由是正确的,但我会建议其他解决方案。当关闭 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
}
}
}
}