我对编程相当陌生,环顾四周后,我想我应该在这里问一下。我基本上需要在TextField
中键入的文本是不可删除的,尽管可以添加/键入额外的文本。
另一种方法是创建一个没有删除键的自定义键盘,尽管我找不到一个好的起点,如在研究等中这样做在SwiftUI。
我有一个基本的TextField
设置和一个空的Binding<String>
寻找我应该研究或学习的指示。
谢谢。
这个想法是创建UITextField类并使用uiviewrepresable绑定SwiftUI视图。这样,您就可以使用所有委托方法并检测退格。此外,使用它可以防止从点击动作中剪切和删除。
UndeletableTextField自定义类
class UndeletableTextField: UITextField {
// This for prevent to cut and delete
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.delete(_:)) ||
action == #selector(UIResponderStandardEditActions.cut(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
UIViewRepresentable视图
struct UndeletableTextFieldUI: UIViewRepresentable {
@Binding var text: String
var placeholder: String
func makeUIView(context: Context) -> UndeletableTextField {
let textField = UndeletableTextField(frame: .zero)
textField.delegate = context.coordinator
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UndeletableTextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: UndeletableTextFieldUI
init(parent: UndeletableTextFieldUI) {
self.parent = parent
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Here we detect backspace and ignore it.
if let char = string.cString(using: String.Encoding.utf8) {
let isBackSpace = strcmp(char, "\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
return false
}
}
return true
}
}
}
ContentView
struct ContentView: View {
@State private var text: String = ""
var body: some View {
UndeletableTextFieldUI(text: $text, placeholder: "Type here")
}
}
您可能需要为该String定制绑定。下面是一个超级基本的例子——你可能想要涵盖更多的边缘情况。请注意,我选择在ObservableObject
中包含逻辑,但是您可以通过将_textStore更改为@State
变量来在View
结构中执行相同的操作。您还需要包含用于初始文本等的逻辑。
class ViewModel : ObservableObject {
var _textStore = ""
var textBinding : Binding<String> {
Binding<String>(get: {
return _textStore
}, set: { newValue in
//do something here to compare newValue to what existed before
//note that this solution will allow text to be both prepended and appended to the existing text
if _textStore.contains(newValue) { _textStore = newValue }
})
}
}
...
@ObservedObject var vm = ViewModel()
TextField("", vm.textBinding)