このコードでは、PasswordDigitViewとPasswordButtonViewという2つのビューを作成し、それらをPasswordViewの中で組み合わせてパスワード入力画面を構築しています。
PasswordDigitViewは、パスワードの各桁を表示するためのビューで、PasswordButtonViewは数字ボタンや削除ボタン、リセットボタンなどの入力用のボタンを表示するためのビューです。PasswordButtonViewでは、ボタンのスタイルを定義するためのPasswordButtonStyleも定義されています。
PasswordViewでは、状態を管理するための@Stateというプロパティラッパーを使って、現在のパスワードを表す配列passwordを宣言しています。パスワードを追加するappendPassword、削除するdeletePassword、リセットするresetPasswordという3つの関数が実装されており、数字ボタンや削除ボタン、リセットボタンがタップされたときにそれぞれ呼び出されます。
最後に、プレビュー用のコードが定義されています。これにより、Xcodeのプレビュー画面でパスワード入力画面を確認することができます。
import SwiftUI
// パスワードを表示するためのビュー
struct PasswordDigitView: View {
var digit: Character?
var body: some View {
RoundedRectangle(cornerRadius: 8)
.frame(width: 40, height: 40)
.overlay(
Text(digit.map(String.init) ?? "")
.font(.title)
.foregroundColor(.primary)
)
.foregroundColor(.secondary.opacity(0.2))
}
}
// パスワード入力用のボタン
struct PasswordButtonView: View {
let title: String
let systemImageName: String?
let action: () -> Void
init(title: String, systemImageName: String? = nil, action: @escaping () -> Void) {
self.title = title
self.systemImageName = systemImageName
self.action = action
}
var body: some View {
Button(action: action) {
if let systemImageName = systemImageName {
Image(systemName: systemImageName)
} else {
Text(title)
.font(.title)
}
}
.buttonStyle(PasswordButtonStyle())
}
}
// ボタンのスタイル
struct PasswordButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(8)
.frame(width: 80, height: 80)
.background(Color.secondary.opacity(0.2))
.clipShape(Circle())
.scaleEffect(configuration.isPressed ? 0.9 : 1.0)
}
}
// パスワード入力画面
struct PasswordView: View {
@State private var password = Array(repeating: Character("_"), count: 6)
var body: some View {
VStack(spacing: 16) {
Text("Enter your passcode")
.font(.title)
.fontWeight(.bold)
HStack(spacing: 16) {
ForEach(password.indices) { index in
PasswordDigitView(digit: password[index])
}
}
VStack(spacing: 16) {
HStack(spacing: 16) {
PasswordButtonView(title: "1") { appendPassword("1") }
PasswordButtonView(title: "2") { appendPassword("2") }
PasswordButtonView(title: "3") { appendPassword("3") }
}
HStack(spacing: 16) {
PasswordButtonView(title: "4") { appendPassword("4") }
PasswordButtonView(title: "5") { appendPassword("5") }
PasswordButtonView(title: "6") { appendPassword("6") }
}
HStack(spacing: 16) {
PasswordButtonView(title: "7") { appendPassword("7") }
PasswordButtonView(title: "8") { appendPassword("8") }
PasswordButtonView(title: "9") { appendPassword("9") }
}
HStack(spacing: 16) {
PasswordButtonView(systemImageName: "delete.left") { deletePassword() }
PasswordButtonView(title: "0") { appendPassword("0") }
PasswordButtonView(systemImageName: "arrow.counterclockwise") { resetPassword() }
}
}
.padding(.bottom)
}
// パスワードを追加する
private func appendPassword(_ digit: String) {
for i in password.indices {
if password[i] == "_" {
password[i] = Character(digit)
if i == password.count - 1 {
// 入力が完了したら何か処理をする
print("Password entered: \(String(password))")
}
break
}
}
}
// パスワードを削除する
private func deletePassword() {
for i in (0..<password.count).reversed() {
if password[i] != "_" {
password[i] = Character("_")
break
}
}
}
// パスワードをリセットする
private func resetPassword() {
password = Array(repeating: Character("_"), count: password.count)
}
}
// プレビュー用のコード
struct PasswordView_Previews: PreviewProvider {
static var previews: some View {
PasswordView()
}
}