.package(url: "https://github.com/mesqueeb/Debouncify", from: "0.1.0")
onChangeDebounced
是一个 SwiftUI View 修饰符,类似于 onChange
,但它会在每次调用时根据指定的持续时间进行防抖处理。Debouncify
是一个 Swift Actor,可以轻松地包装一个函数,使其在每次调用时根据指定的持续时间进行防抖处理。“防抖”是指在短时间内延迟执行一个函数。如果在该时间内该函数被调用两次,则该函数仅在最后一次调用后经过指定的持续时间后执行一次。
假设您有一个函数,您希望在每次按键时执行,但希望通过 300 毫秒进行防抖,以便仅在用户停止输入一段时间后才执行它。
示例
@State private var query: String = ""
func search(_ query: String) async {
print("searching!")
// your search API call logic...
}
var body: some View {
TextField("Search...", text: $query)
.onChangeDebounced(of: query, after: .milliseconds(300)) { _oldValue, newValue in
search(newValue)
}
}
如果您需要取消搜索函数的防抖执行,例如当用户按下 ESC 键时,您可以传递一个包含 Task
的 Binding,然后您可以取消该 Task
。
示例
@State private var query: String = ""
func search(_ query: String) async {
print("searching!")
// your search API call logic...
}
/// The search Task is added by `onChangeDebounced` below
@State private var searchTask: Task<Void, never>? = nil
var body: some View {
TextField("Search...", text: $query)
.onChangeDebounced(of: query, after: .milliseconds(300), task: $searchTask) { _oldValue, newValue in
search(newValue)
}
.onKeyPress(.return) {
searchTask?.cancel()
search(query)
return .handled
}
.onKeyPress(.escape) {
searchTask?.cancel()
return .handled
}
}
使用 Debouncify
包装一个函数,它会自动在每次后续调用时进行防抖处理。
示例
// Example debounced function
func search() async {
print("searching!")
// your search API call logic...
}
// Using Debouncify to wrap the function
let searchAfter300ms = Debouncify(call: search, after: .milliseconds(300))
// Usage
Task {
Task { await searchAfter300ms() }
try await Task.sleep(for: .milliseconds(100))
Task { await searchAfter300ms() }
try await Task.sleep(for: .milliseconds(100))
Task { await searchAfter300ms() }
}
// it will only print "searching!" once after 300ms
您可以通过调用 Debouncify
实例上的 cancel
方法来取消防抖任务。
示例
// Example debounced function
func search() async {}
let searchAfter300ms = Debouncify(by: .milliseconds(300), search)
var task: Task<Any, Any>? = nil
Task { await searchAfter300ms() }
// if the search needs to be cancelled before the Task above finishes
Task { await searchAfter300ms.cancel() }
有关更多信息,请参阅文档。