0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【SwiftUI】Combineでテキストフィールドの文字数制限を実装してみた

Posted at

はじめに

比較して学ぶRxSwift入門」という書籍にあったテキストフィールドの文字数制限をCombineで実装してみました

完成形

Simulator Screen Recording - iPhone 14 Pro - 2022-11-01 at 12.38.24.gif

実装

ContentView.swift
import SwiftUI

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    var body: some View {
        VStack {
            TextField("名前", text: $viewModel.name)
                .textFieldStyle(.roundedBorder)
            Text(viewModel.nameLimitText)
                .foregroundColor(viewModel.nameLimitTextColor)
                .frame(maxWidth: .infinity, alignment: .trailing)
            TextField("住所", text: $viewModel.address)
                .textFieldStyle(.roundedBorder)
            Text(viewModel.addressLimitText)
                .foregroundColor(viewModel.addressLimitTextColor)
                .frame(maxWidth: .infinity, alignment: .trailing)
        }
        .padding()
    }
}
ViewModel.swift
import SwiftUI
import Combine

final class ViewModel: ObservableObject {
    @Published var name: String = ""
    @Published var address: String = ""
    @Published var nameLimitText: String = ""
    @Published var addressLimitText: String = ""

    @Published var nameLimitTextColor: Color = .primary
    @Published var addressLimitTextColor: Color = .primary

    private let maxNameLength = 10
    private let maxAddressLength = 20

    private var cancellables = Set<AnyCancellable>()

    init() {
        $name
            .map { $0.count }
            .sink { [weak self] count in
                guard let self else { return }
                let length = self.maxNameLength - count
                self.nameLimitText = length >= 0 ? "あと\(length)文字です" : "名前は\(self.maxNameLength)文字以内で設定してください"
                self.nameLimitTextColor = length >= 0 ? Color.primary : Color.red
            }
            .store(in: &cancellables)

        $address
            .map { $0.count }
            .sink { [weak self] count in
                guard let self else { return }
                let length = self.maxAddressLength - count
                self.addressLimitText = length >= 0 ? "あと\(length)文字です" : "住所は\(self.maxAddressLength)文字以内で設定してください"
                self.addressLimitTextColor = length >= 0 ? Color.primary : Color.red
            }
            .store(in: &cancellables)
    }
}

おわり

View側がスッキリしていてコードが見やすくなりました

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?