LoginSignup
1
3

More than 1 year has passed since last update.

[SwiftUI]TextFieldのテキスト入力監視処理のサンプル

Posted at

TextFieldの入力にCombineCurrentValueSubjectを使用してその値の変更を購読するという方針で行きます。

ViewModelの実装

TextInputViewModel.swift
import Foundation
import Combine

@MainActor
class TextInputViewModel: ObservableObject {
    @Published var resultText: String = ""
    @Published var inputText = CurrentValueSubject<String, Never>("")

    private var cancellables = [AnyCancellable]()

    func subscribeInputText() {
        inputText
            .debounce(for: 1, scheduler: RunLoop.main)
            .removeDuplicates()
            .sink {[weak self] value in
                guard let self = self else { return }
                self.resultText = value
                // TODO: 検索候補の取得等
            }
            .store(in: &cancellables)
    }

}

  • .debounce(for: 1, scheduler: RunLoop.main)
    これで入力中の処理を1秒間遅延させて連続で値が流れないようにします。

  • .removeDuplicates()
    以前と同じ値を弾きます。

  • .sink
    でresultTextに直接Stringを渡していますが、本来なら検索処理だったり検索候補を取得などの処理をすることが考えられます。

View側の実装

TextInputView.swift
import SwiftUI

struct TextInputView: View {
    @StateObject var viewModel: TextInputViewModel

    var body: some View {
        VStack {
            TextField("placeholder", text: $viewModel.inputText.value)
            .padding()
            .border(.red, width: 1.0)
            .padding(.bottom, 20)
            Text(viewModel.resultText)
        }
        .padding()
        .onAppear {
            viewModel.subscribeInputText()
        }
    }
}

  • TextField("placeholder", text: $viewModel.inputText.value)
    ViewModelのCurrentValueSubjectをBindingします。

  • .padding().border(.red, width: 1.0)
    こちらは先にpaddingを入れることでボーダーの内部に隙間を入れています。

  • Text(viewModel.resultText)
    入力結果をそのまま表示するラベルです。

  • .onAppear
    ここでviewModel.subscribeInputText() TextFieldinputTextの監視を開始する関数を呼び出します。

結果

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3