ios - 如何在空文本字段中更改 deleteBackward 上的 firstResponder
问题描述
共有三个文本字段。
Q1:如何将光标(更改firstResponder)移动到第一个textField,当在空的第二个中按下向后删除时。
Q2:有没有办法通过 Combine 订阅 deleteBackward() 事件?
Q3:我的代码在 iOS 14.5 上运行良好,但在 15.0 上捕获“AttributeGraph:通过属性检测到循环”。任何想法为什么以及如何解决它?
struct ContentView: View {
@State var text1 = ""
@State var text2 = ""
@State var text3 = ""
@State private var isFirstResponder: [Bool] = [true, false, false]
var body: some View {
HStack {
CustomTextField(text: $text1, tag: 0, returnValue: .next, isFirstResponder: $isFirstResponder)
.modifier(TextFieldStyle())
CustomTextField(text: $text2, tag: 1, returnValue: .next, isFirstResponder: $isFirstResponder)
.modifier(TextFieldStyle())
CustomTextField(text: $text2, tag: 2, returnValue: .next, isFirstResponder: $isFirstResponder)
.modifier(TextFieldStyle())
}
.frame(height: 40)
.padding()
}
}
struct TextFieldStyle: ViewModifier {
func body(content: Content) -> some View {
content
.padding(.all, 10)
.background(RoundedRectangle(cornerRadius: 5).fill(Color.white))
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(lineWidth: 1)
)
.foregroundColor(Color.black.opacity(0.7))
}
}
private class CustomUITextField: UITextField {
override public func deleteBackward() {
print("deleteBackward")
super.deleteBackward()
if text == "" {
print("deleteBackward on empty")
}
}
}
struct CustomTextField: UIViewRepresentable {
@Binding var text: String
let tag: Int
let returnValue: UIReturnKeyType
@Binding var isFirstResponder: [Bool]
func makeUIView(context: Context) -> UITextField {
let textField = CustomUITextField(frame: .zero)
textField.keyboardType = .numberPad
textField.autocorrectionType = .no
textField.returnKeyType = returnValue
textField.tag = tag
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
if isFirstResponder[tag] {
uiView.becomeFirstResponder()
} else {
uiView.resignFirstResponder()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(text: $text, self)
}
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
var parent: CustomTextField
init(text: Binding<String>, _ textField: CustomTextField) {
_text = text
parent = textField
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentText = textField.text ?? ""
var isDeleting = string.count == 0
if (currentText + string).count == 1 && !isDeleting {
parent.isFirstResponder = [false, false, false]
parent.isFirstResponder[min(parent.tag + 1, 2)] = true
} else if currentText.count <= 1 && isDeleting {
parent.isFirstResponder = [false, false, false]
parent.isFirstResponder[max(parent.tag - 1, 0)] = true
} else if (currentText + string).count > 3 {
return false
}
print("textField \(currentText) -> \(string)")
return true
}
}
}
解决方案
推荐阅读
- sql - SQL通过ID从另一个表中获取列的总和
- vue.js - 在Vue中制作链接组件的链接列表组件
- c# - 为什么 MVVM 模式不适用于 ChartValues?
- php - 属性“id”取自非对象
- python - Python elementtree 获取 XML CDATA
- javascript - 如果节点属性与功能混淆,如何突出显示错误,反之亦然。例如,显示 `node.innerText()` 或 `node.toLowerCase` 的错误
- java - 如何打破某些语句的扫描仪并为其他语句运行
- r - 如何在r中选择具有特定值的行?
- sql - 返回最高计数记录
- flutter - 无法创建渡槽项目