ios - SwiftUI 结合 Debounce TextField

标签 ios xcode swiftui combine

我有一个具有 SwiftUI 应用程序生命周期的 SwiftUI 应用程序。我正在尝试设置一种标准的添加方式
键入 debounce 到 TextFields。理想情况下,我想创建自己的 TextField 修饰符
可以很容易地应用于需要编辑许多文本字段的 View 。我试过一堆
方法来做到这一点,但我必须错过一些基本的东西。这是一个例子。这个
不起作用:

struct ContentView: View {

    @State private var searchText = ""
    
    var body: some View {
    
        VStack {
            Text("You entered: \(searchText)")
                .padding()
            TextField("Enter Something", text: $searchText)
                .frame(height: 30)
                .padding(.leading, 5)
                .overlay(
                    RoundedRectangle(cornerRadius: 6)
                        .stroke(Color.blue, lineWidth: 1)
                )
                .padding(.horizontal, 20)
                .onChange(of: searchText, perform: { _ in
                    var subscriptions = Set<AnyCancellable>()
                
                    let pub = PassthroughSubject<String, Never>()
                    pub
                        .debounce(for: .seconds(1), scheduler: DispatchQueue.main)
                        .collect()
                        .sink(receiveValue: { t in
                            self.searchText = t.first ?? "nothing"
                        } )
                        .store(in: &subscriptions)
                })
        }
    }
}
任何指导将不胜感激。 Xcode 12.4,iOS 14.4

最佳答案

我认为您必须保留两个变量:一个用于用户键入时字段中的文本,另一个用于去抖动文本。否则,用户将看不到实时输入的输入,我假设这不是您想要的行为。我猜这可能是针对更标准的用例,例如,一旦用户暂停输入,就执行数据提取。
我喜欢 ObservableObjects 和 Combine 来管理这类事情:

class TextFieldObserver : ObservableObject {
    @Published var debouncedText = ""
    @Published var searchText = ""
    
    private var subscriptions = Set<AnyCancellable>()
    
    init() {
        $searchText
            .debounce(for: .seconds(1), scheduler: DispatchQueue.main)
            .sink(receiveValue: { [weak self] t in
                self?.debouncedText = t
            } )
            .store(in: &subscriptions)
    }
}

struct ContentView: View {
    @StateObject var textObserver = TextFieldObserver()
    
    @State var customText = ""
    
    var body: some View {
    
        VStack {
            Text("You entered: \(textObserver.debouncedText)")
                .padding()
            TextField("Enter Something", text: $textObserver.searchText)
                .frame(height: 30)
                .padding(.leading, 5)
                .overlay(
                    RoundedRectangle(cornerRadius: 6)
                        .stroke(Color.blue, lineWidth: 1)
                )
                .padding(.horizontal, 20)
            Divider()
            Text(customText)
            TextFieldWithDebounce(debouncedText: $customText)
        }
    }
}
struct TextFieldWithDebounce : View {
    @Binding var debouncedText : String
    @StateObject private var textObserver = TextFieldObserver()
    
    var body: some View {
    
        VStack {
            TextField("Enter Something", text: $textObserver.searchText)
                .frame(height: 30)
                .padding(.leading, 5)
                .overlay(
                    RoundedRectangle(cornerRadius: 6)
                        .stroke(Color.blue, lineWidth: 1)
                )
                .padding(.horizontal, 20)
        }.onReceive(textObserver.$debouncedText) { (val) in
            debouncedText = val
        }
    }
}
我包括了两个例子——顶部,容器 View ( ContentView )拥有 ObservableObject 和底部,它被制成一个更可重用的组件。

关于ios - SwiftUI 结合 Debounce TextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66164898/

相关文章:

swift - 如何在 macOS 中的 SwiftUI 中制作一个简单的圆形按钮?

swiftui - 如何在一个VStack中添加两个NavigationLink

php - 输入类型 "file"在 iPad 上不起作用

ios - 如何将数据从两个 UITextView 保存到 UserDefaults

ios - 我可以在 iOS 中测量蓝牙信号强度吗?

ios - iphone X 自动将纵向旋转为纵向?

swift - 新 Xcode (10.2) 的 dyld : Library not loaded: @rpath/libswiftCore. dylib 问题

ios - Swift 希望将#selector 的参数暴露给 Objective-C

swiftui - @FocusState 以编程方式生成的 TextField

ios - 快速动画不工作