Created
July 26, 2023 03:13
-
-
Save pexavc/14c96f343699c787c658491a81021799 to your computer and use it in GitHub Desktop.
Simple Search Query Debouncer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import SwiftUI | |
import Combine | |
class SearchConductor: ObservableObject { | |
var searchTimer: Timer? = nil | |
private var task: Task<Void, Error>? = nil | |
@Published var query: String | |
@Published var isEditing: Bool = false | |
@Published var isSearching: Bool = false | |
@Published var response: SearchResponse? = nil | |
var isEmpty: Bool { | |
response == nil | |
} | |
private var handler: ((String) async -> SearchResponse?)? | |
internal var cancellables: Set<AnyCancellable> = .init() | |
init() { | |
query = "" | |
self.handler = nil | |
$query | |
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } | |
.removeDuplicates() | |
.sink { [weak self] value in | |
// guard value.isNotEmpty else { | |
// self?.clean() | |
// return | |
// } | |
self?.startTimer() | |
}.store(in: &cancellables) | |
} | |
@discardableResult | |
func hook(_ commit: @escaping ((String) async -> SearchResponse?)) -> Self { | |
self.handler = commit | |
return self | |
} | |
//basic debouncing | |
func startTimer() { | |
searchTimer?.invalidate() | |
searchTimer = nil | |
isSearching = true | |
searchTimer = Timer.scheduledTimer( | |
withTimeInterval: 0.4.randomBetween(0.8), | |
repeats: false) { [weak self] timer in | |
timer.invalidate() | |
guard let q = self?.query else { return } | |
self?.task?.cancel() | |
self?.task = Task.detached { [weak self] in | |
let response = await self?.handler?(q) | |
DispatchQueue.main.async { [weak self] in | |
GraniteHaptic.light.invoke() | |
self?.response = response | |
self?.isSearching = false | |
} | |
} | |
} | |
} | |
func clean() { | |
isSearching = false | |
self.task?.cancel() | |
self.task = nil | |
searchTimer?.invalidate() | |
searchTimer = nil | |
query = "" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example use: