はじめに
ログイン画面などで全ての情報が入力されていない場合、ログインボタンを押せなくする動きを再現してみました。
複数の値をまとめて監視する方法を使用することで簡潔に書けたので紹介します。
サンプルアプリ
実装
View
import SwiftUI
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationStack {
List {
Section {
TextField("氏名", text: $viewModel.name)
Stepper(value: $viewModel.age) {
Text("年齢: \(viewModel.age.description)")
}
} header: {
Text("基本情報")
}
Section {
TextField("ユーザーネーム", text: $viewModel.username)
SecureField("パスワード", text: $viewModel.password)
} header: {
Text("アカウント情報")
}
Section {
loginButton
}
}
.listStyle(.insetGrouped)
.navigationTitle("ログイン")
}
}
private var loginButton: some View {
Button {
} label: {
Text("ログイン")
.font(.system(size: 20, weight: .black))
.frame(maxWidth: .infinity, alignment: .center)
}
.disabled(viewModel.isEnableLoginButton)
}
}
ViewModel
import Combine
final class ViewModel: ObservableObject {
@Published var name: String = ""
@Published var age: Int = 0
@Published var username: String = ""
@Published var password: String = ""
@Published var isEnableLoginButton: Bool = false
init() {
$name.combineLatest($age, $username, $password)
.map { $0 == "" || $1 == 0 || $2 == "" || $3 == "" }
.assign(to: &$isEnableLoginButton)
}
}
解説
以下のコードでname, age, username, passwordを監視する指示を行っています。
$name.combineLatest($age, $username, $password)
以下のコードでそれぞれの値に入力が行われたかを判定しています。
.map { $0 == "" || $1 == 0 || $2 == "" || $3 == "" }
$0
にはname
の値
$1
にはage
の値
$2
にはusername
の値
$3
にはpassword
の値
以下のコードでmapの結果をisEnableLoginButton
に代入しています。
.assign(to: &$isEnableLoginButton)
おわり
便利ですね