I am using a boolean (searchVM.showSearchView: Bool) to simultaneously turn opacity of a SearchView to 1.0 AND show/hide a UIRepresentableKeyboard.
This gives me the same functionality as Google Maps when you tap on the search bar and (simultaneously) the white search view appears, textfield focused, and keyboard showing.
However I am getting the below message print twice every time I set the showSearchView to true.
=== AttributeGraph: cycle detected through attribute 320536 ===
=== AttributeGraph: cycle detected through attribute 318224 ===
Why am I getting this message? Is it the passing around of my searchVM?
SearchViewModel
class SearchViewModel: ObservableObject {
var text: String = ""
@Published var showSearchView: Bool = false
}
Textfield & Cancel button
struct SearchBar: View {
@ObservedObject var searchVM: SearchViewModel
@State var text: String = ""
var body: some View {
HStack {
FirstResponderTextfield(searchVM: searchVM, text: $text, placeholder: "Search")
Text("Cancel")
.onTapGesture {
searchVM.showSearchView.toggle()
}
}
}
}
FirstResponderTextField
struct FirstResponderTextfield: UIViewRepresentable {
@ObservedObject var searchVM : SearchViewModel
@Binding var text: String
let placeholder: String
// COORDINATOR
class TextFieldCoordinator: NSObject, UITextFieldDelegate {
var control: FirstResponderTextfield
@Binding var text: String // unused but required
func textFieldDidChangeSelection(_ textField: UITextField) {
control.searchVM.text = textField.text ?? ""
}
func textFieldDidEndEditing(_ textField: UITextField) {
}
init(control: FirstResponderTextfield, text: Binding<String>) {
self.control = control
self._text = text
}
}
func makeCoordinator() -> TextFieldCoordinator {
return TextFieldCoordinator(control: self, text: $text)
}
func makeUIView(context: Context) -> some UIView {
let textField = UITextField()
textField.delegate = context.coordinator
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UIViewType, context: Context) {
if searchVM.showSearchView {
uiView.becomeFirstResponder() // show keyboard
} else {
uiView.resignFirstResponder() // dismiss keyboard
}
}
}