SwiftUIでiOSの純正のパスワード入力画面を実装

このコードでは、PasswordDigitViewとPasswordButtonViewという2つのビューを作成し、それらをPasswordViewの中で組み合わせてパスワード入力画面を構築しています。

PasswordDigitViewは、パスワードの各桁を表示するためのビューで、PasswordButtonViewは数字ボタンや削除ボタン、リセットボタンなどの入力用のボタンを表示するためのビューです。PasswordButtonViewでは、ボタンのスタイルを定義するためのPasswordButtonStyleも定義されています。

PasswordViewでは、状態を管理するための@Stateというプロパティラッパーを使って、現在のパスワードを表す配列passwordを宣言しています。パスワードを追加するappendPassword、削除するdeletePassword、リセットするresetPasswordという3つの関数が実装されており、数字ボタンや削除ボタン、リセットボタンがタップされたときにそれぞれ呼び出されます。

最後に、プレビュー用のコードが定義されています。これにより、Xcodeのプレビュー画面でパスワード入力画面を確認することができます。

```swift

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()
    }
}



```