Skip to content

Instantly share code, notes, and snippets.

@Clarko
Last active December 9, 2021 22:34
Show Gist options
  • Save Clarko/af11fab2fb1e194214eb62f46adae50d to your computer and use it in GitHub Desktop.
Save Clarko/af11fab2fb1e194214eb62f46adae50d to your computer and use it in GitHub Desktop.
SwiftUI search field with a keyboard focus binding
// ⚠️ As of WWDC21 you can use SwiftUI .searchable
// https://developer.apple.com/documentation/swiftui/list/searchable(text:placement:)
//
// SearchField.swift
//
// Created by Clarko on 7/17/20.
//
// SwiftUI doesn't have a SearchField yet, so here's one from UIKit.
//
// The isEditing binding lets you react to keyboard focus changes,
// or control the state of keyboard focus yourself.
//
import SwiftUI
struct SearchField: UIViewRepresentable {
var title: String
@Binding var text: String
@Binding var isEditing: Bool
init(_ title: String, text: Binding<String>, isEditing: Binding<Bool>) {
self.title = title
self._text = text
self._isEditing = isEditing
}
func makeUIView(context: UIViewRepresentableContext<SearchField>) -> UISearchBar {
let uiSearchBar = UISearchBar()
// Customize appearance
uiSearchBar.autocapitalizationType = .none
uiSearchBar.autocorrectionType = .default
uiSearchBar.enablesReturnKeyAutomatically = false
uiSearchBar.keyboardType = .default
uiSearchBar.returnKeyType = .done
uiSearchBar.searchBarStyle = .minimal
uiSearchBar.delegate = context.coordinator
return uiSearchBar
}
func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchField>) {
// SwiftUI doesn't like it when you modify state during a view update
context.coordinator.safeToModifyState = false
uiView.text = text
uiView.placeholder = title
if isEditing {
uiView.becomeFirstResponder()
} else {
uiView.resignFirstResponder()
}
context.coordinator.safeToModifyState = true
}
func makeCoordinator() -> SearchField.Coordinator {
return Coordinator(text: $text, isEditing: $isEditing)
}
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
@Binding var isEditing: Bool
var safeToModifyState = true
init(text: Binding<String>, isEditing: Binding<Bool>) {
_text = text
_isEditing = isEditing
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if safeToModifyState {
text = searchText
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if safeToModifyState {
isEditing = false
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
if safeToModifyState {
isEditing = true
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
if safeToModifyState {
isEditing = false
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment