Skip to content

Instantly share code, notes, and snippets.

@akardas16
Created August 31, 2022 19:49
Show Gist options
  • Save akardas16/5ee5c7c767a9cc46fe3e657d9d78f408 to your computer and use it in GitHub Desktop.
Save akardas16/5ee5c7c767a9cc46fe3e657d9d78f408 to your computer and use it in GitHub Desktop.
SearchBar example with suggestions
//
// SearchBarView.swift
// CombineApp
//
// Created by Abdullah Kardas on 31.08.2022.
//
import SwiftUI
import Combine
struct CityModel:Identifiable {
let id: UUID = UUID()
let name:String
let degree:Double
}
class SearchBarViewModel:ObservableObject {
@Published var text:String = ""
@Published var cityList = [CityModel(name: "New York", degree: 25),CityModel(name: "Washington", degree: 20.4),CityModel(name: "New Jersey", degree: 14),CityModel(name: "New Mexico", degree: 25),CityModel(name: "Chicago", degree: 25),CityModel(name: "Boston", degree: 17),CityModel(name: "Los Angeles", degree: 8)]
@Published var fileteredList:[CityModel] = []
var cancallable = Set<AnyCancellable>()
init(){
$text.map { txt in
var model:[CityModel] = []
for city in self.cityList where city.name.lowercased().contains(txt.lowercased()) {
model.append(city)
}
return model
}.sink { newModel in
self.fileteredList = newModel
}.store(in: &cancallable)
}
}
struct SearchBarView: View {
@State var isKeyboardPresented = false
@StateObject var vm = SearchBarViewModel()
@State var city:CityModel = CityModel(name: "Los Angeles", degree: 0)
var body: some View {
ZStack(alignment:.top) {
VStack{
//Search
HStack(spacing:0) {
HStack(spacing:8){
Image(systemName: "magnifyingglass")
TextField("Search any city...", text: $vm.text).autocorrectionDisabled(true)
Image(systemName: "xmark.circle.fill").foregroundColor(.gray).opacity(vm.text.count > 0 ? 1:0)
.onTapGesture {
vm.text = ""
}
}.padding(.horizontal).padding(.vertical,12).background (
Capsule(style: .circular).fill(.gray.opacity(0.3))
).padding(.horizontal,6)
if isKeyboardPresented {
Text("Cancel").foregroundColor(.blue)
.padding(.trailing,6)
.onTapGesture {
vm.text = ""
hideKeyboard()
isKeyboardPresented = false
}
}
}.onReceive(keyboardPublisher) { value in
isKeyboardPresented = value
}
//Search List
if vm.text.count > 0 {
List {
ForEach(vm.fileteredList) { city in
Text(city.name).onTapGesture {
self.city = city
vm.text = ""
hideKeyboard()
isKeyboardPresented = false
}
}
}.listStyle(.plain)
}
Spacer()
Text(city.name).font(.largeTitle).bold()
Text("\(Int(city.degree)) °C").font(.largeTitle)
Spacer()
}
}
}
}
struct SearchBarView_Previews: PreviewProvider {
static var previews: some View {
SearchBarView()
}
}
extension View {
func hideKeyboard() {
let resign = #selector(UIResponder.resignFirstResponder)
UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
}
}
extension View {//Listen keyboard changes
var keyboardPublisher: AnyPublisher<Bool, Never> {
Publishers
.Merge(
NotificationCenter
.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.map { _ in true },
NotificationCenter
.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ in false })
.debounce(for: .seconds(0.1), scheduler: RunLoop.main)
.eraseToAnyPublisher()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment