みんなは、どんな実装にしていますか。
入力文字を監視しつつの検索結果のリアルタイム反映的なやつを作るとき。
詰まる感じをどう解消していますか。
Debounce
only emit an item from an Observable if a particular timespan has passed without it emitting another item
👉 ReactiveX - Debounce operator
👉 debounce(for:scheduler:options:) | Apple Developer Documentation
import Combine
public final class DebounceObject: ObservableObject {
@Published var text: String = ""
@Published var debouncedText: String = ""
private var bag = Set<AnyCancellable>()
public init(dueTime: TimeInterval = 0.5) {
$text
.removeDuplicates()
.debounce(for: .seconds(dueTime), scheduler: DispatchQueue.main)
.sink(receiveValue: { [weak self] value in
self?.debouncedText = value
})
.store(in: &bag)
}
}
struct SearchView: View {
@StateObject var debounceObject = DebounceObject()
var body: some View {
VStack {
TextField(text: $debounceObject.text)
.onChange(of: debounceObject.debouncedText) { text in
// perform search
}
}
}
}
👉 How to debounce TextField search in SwiftUI | Swift Discovery
combine てのもう時代遅れなのですか ?
今現在、本流の本筋の考え方のわかりやすいシンプルな記述を探します。
🤔 Tunous/DebouncedOnChange
非同期処理とはいえ、cancel や exception の伝播は無視してもいいのではないか。
extension Task {
@discardableResult
public static func delayed(
seconds: TimeInterval,
operation: @escaping @Sendable () async -> Void
) -> Self where Success == Void, Failure == Never {
Self {
do {
try await Task<Never, Never>.sleep(seconds: seconds)
await operation()
} catch {}
}
}
static func sleep(seconds: TimeInterval) async throws where Success == Never, Failure == Never {
try await Task<Success, Failure>.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
}
}
👉 Tunous/DebouncedOnChange: SwiftUI onChange View extension with debounce time
( 引き続き調査中... )
【SwiftUI】Search TextField を作る #2 https://t.co/QjazuyLm3B #swift #プログラミング初心者
— chanzmao (@maochanz) April 19, 2024
【SwiftUI】ScrollView や List を snap する
👉 https://t.co/z6XUoo9RIA#プログラミング #Swift pic.twitter.com/F166h7dyd9— chanzmao (@maochanz) April 24, 2024