【发布时间】:2020-02-14 23:27:06
【问题描述】:
我创建了一个自定义文本字段,我想利用 Combine。为了在我的文本字段中的文本更改时收到通知,我目前使用自定义修饰符。它运行良好,但我希望此代码可以在我的 CustomTextField 结构中。
我的 CustomTextField 结构符合 UIViewRepresentable。在这个结构中,有一个名为 Coordinator 的 NSObject 类,它符合 UITextFieldDelegate。
我已经在使用其他 UITextField 委托方法,但找不到与我的自定义修饰符完全一样的方法。有些方法很接近,但并不完全按照我想要的方式行事。无论如何,我觉得最好将这个新的自定义 textFieldDidChange 方法放在 Coordinator 类中。
这是我的自定义修饰符
private let textFieldDidChange = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification)
.map { $0.object as! UITextField}
struct CustomModifer: ViewModifier {
func body(content: Content) -> some View {
content
.tag(1)
.onReceive(textFieldDidChange) { data in
//do something
}
}
}
我的 CustomTextField 用于 SwiftUI 视图,并附加了我的自定义修饰符。当文本字段发生变化时,我可以做一些事情。修改器也在使用组合。它工作得很好,但我不希望这个功能以修饰符的形式出现。我想在我的 Coordinator 类中使用它,以及我的 UITextFieldDelegate 方法。
这是我的自定义文本字段
struct CustomTextField: UIViewRepresentable {
var isFirstResponder: Bool = false
@EnvironmentObject var authenticationViewModel: AuthenticationViewModel
func makeCoordinator() -> Coordinator {
return Coordinator(authenticationViewModel: self._authenticationViewModel)
}
class Coordinator: NSObject, UITextFieldDelegate {
var didBecomeFirstResponder = false
@EnvironmentObject var authenticationViewModel: AuthenticationViewModel
init(authenticationViewModel: EnvironmentObject<AuthenticationViewModel>)
{
self._authenticationViewModel = authenticationViewModel
}
// Limit the amount of characters that can be typed in the field
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentText = textField.text ?? ""
guard let stringRange = Range(range, in: currentText) else { return false }
let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
return updatedText.count <= 14
}
/* I want to put my textFieldDidChange method right here */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
func textFieldDidEndEditing(_ textField: UITextField) {
textField.resignFirstResponder()
textField.endEditing(true)
}
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.delegate = context.coordinator
textField.placeholder = context.coordinator.authenticationViewModel.placeholder
textField.font = .systemFont(ofSize: 33, weight: .bold)
textField.keyboardType = .numberPad
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
let textField = uiView
textField.text = self.authenticationViewModel.text
}
}
struct CustomTextField_Previews: PreviewProvider {
static var previews: some View {
CustomTextField()
.previewLayout(.fixed(width: 270, height: 55))
.previewDisplayName("Custom Textfield")
.previewDevice(.none)
}
}
我一直在观看有关 Combine 的视频,我想开始在我正在构建的新应用中使用它。我真的认为在这种情况下使用它是正确的,但仍然不太确定如何实现它。我真的很感激一个例子。
总结一下:
我想在我的 Coordinator 类中添加一个名为 textFieldDidChange 的函数,并且每次我的文本字段发生更改时都应该触发它。它必须使用 Combine。
提前致谢
【问题讨论】:
-
在 SwiftUI 中没有 UITextFields 或委托方法,所以这个问题有点令人困惑。
-
UIViewRepresentable 允许我们在 SwiftUI 中利用 UIKit。
-
好的,到目前为止一切顺利。我不太明白你为什么不只使用本机 TextField,但我会一起玩。那么我们的目标到底是什么?我们要解决什么问题?
-
我希望每当我的文本字段发生更改时触发一个名为 textFieldDidChange 的函数。我希望这个函数位于符合 UITextFieldDelegate 的类中。在我的例子中,它是我的自定义 UITextField 的 Coordinator 类。现在,我有我想要的功能,但是以修饰符的形式。原生 SwiftUI 文本字段非常有限。没有办法使用 becomeFirstResponder,所以我不得不创建这个自定义文本字段。
标签: swift uitextfield swiftui uitextfielddelegate combine