sin*_*o12 6 ios swift swiftui uiviewrepresentable
我为 SwiftUI 创建了一个UIViewRepresentable包装UITextField,因此我可以在用户点击回车键时更改第一响应者。
这是我的 UIViewRepresentable (我删除了第一响应者代码以保持简单)
struct CustomUIKitTextField: UIViewRepresentable {
@Binding var text: String
var placeholder: String
func makeUIView(context: UIViewRepresentableContext<CustomUIKitTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomUIKitTextField>) {
uiView.text = text
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentCompressionResistancePriority(.required, for: .vertical)
}
func makeCoordinator() -> CustomUIKitTextField.Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: CustomUIKitTextField
init(parent: CustomUIKitTextField) {
self.parent = parent
}
func textFieldDidChangeSelection(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序的第一个屏幕有一个“使用电子邮件登录”按钮,该按钮会推送显示CustomUIKitTextField并使用视图模型的 @Published 属性ObservableObject作为 TextField 文本的 MailView。
struct MailView: View {
@ObservedObject var viewModel: MailSignUpViewModel
var body: some View {
VStack {
CustomUIKitTextField(placeholder: self.viewModel.placeholder,
text: self.$viewModel.mailAddress)
.padding(.top, 30)
.padding(.bottom, 10)
NavigationLink(destination: UsernameView(viewModel: UsernameSignUpViewModel())) {
Text("Next")
}
Spacer()
}
}
}
Run Code Online (Sandbox Code Playgroud)
一切工作正常,直到我推送另一个视图,例如 MailView,例如 UsernameView。它的实现方式完全相同,但不知何故,一旦我完成输入,CustomUIKitTextField就会收到updateUIView一个带有空字符串的调用。
还有其他奇怪的行为,例如当我将 MailView 和 UsernameView 包装在另一个 NavigationView 中时,一切正常。但这显然不是解决它的方法,因为那时我会有多个导航视图。
当在视图模型中使用 @State 属性而不是 @Published 属性时,它也适用。但我不想使用@State,因为我真的想将模型代码保留在视图之外。
有没有人遇到过同样的问题或类似的问题?
看来您\xe2\x80\x99 使用了错误的委托方法。 textFieldDidChangeSelection会产生一些不一致的结果(这听起来像是你\xe2\x80\x99正在处理的)。相反,我建议使用textFieldDidEndEditing它也可以让您访问传入的控制权,但它保证您\xe2\x80\x99在放弃第一响应者时获得该对象。这很重要,因为这意味着您\xe2\x80\x99在属性更改后获取该对象,并且\xe2\x80\x99释放响应者对象。
因此,我将更改您的委托方法,如下所示:
\n\n\nfunc textFieldDidEndEditing(_ textField: UITextField) {\n parent.text = textField.text ?? ""\n}\nRun Code Online (Sandbox Code Playgroud)\n\n有关详细信息,请参阅此textFieldDidEndEditing方法的链接:\n https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619591-textfielddidendediting
有关该UITextFieldDelegate对象的信息的链接:\n https://developer.apple.com/documentation/uikit/uitextfielddelegate
编辑
\n\n根据评论,如果您希望在每次更改一个字符时检查文本,则应该实现此委托函数:
\n\nfunc textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {\n\n // User pressed the delete key\n if string.isEmpty {\n // If you want to update your query string here after the delete key is pressed, you can rebuild it like we are below\n return true\n }\n\n //this will build the full string the user intends so we can use it to build our search\n let currentText = textField.text ?? ""\n let replacementText = (currentText as NSString).replacingCharacters(in: range, with: string)\n // You can set your parent.text here if you like, or you can fire the search function as well\n\n // When you\'re done though, return true to indicate that the textField should display the changes from the user\n\n return true\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
11397 次 |
| 最近记录: |