Я создал настраиваемое текстовое поле и хотел бы воспользоваться преимуществами Combine. Чтобы получать уведомления об изменении текста в моем текстовом поле, я сейчас использую настраиваемый модификатор. Он работает хорошо, но я хочу, чтобы этот код мог быть внутри моей структуры CustomTextField.
Моя структура CustomTextField соответствует UIViewRepresentable. Внутри этой структуры есть класс NSObject под названием Coordinator, который соответствует 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
}
}
}
My CustomTextField используется в представлении SwiftUI с прикрепленным к нему моим настраиваемым модификатором. Я могу что-то делать, когда есть изменения в текстовом поле. Модификатор также использует Combine. Он отлично работает, но я не хочу, чтобы эта функция была в виде модификатора. Я хочу использовать его в своем классе координатора вместе с моими методами UITextFieldDelegate.
Это мое CustomTextField
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 и хотел бы начать использовать его в новом приложении, которое я создаю. Я действительно думаю, что это правильное решение в данной ситуации, но до сих пор не знаю, как это осуществить. Я был бы очень признателен за пример.
Подводя итог:
Я хочу добавить функцию textFieldDidChange в мой класс Coordinator, и она должна запускаться каждый раз, когда в моем текстовом поле происходит изменение. Он должен использовать Combine.
заранее спасибо