SwiftUI

SwiftUI | 회원가입 만들기

ziziDev 2024. 8. 22. 21:19
반응형

회원가입

 

이메일

 

이메일 유효성 검사

let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Z]{2,64}"
let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegEx)

 

애플 로그인

SignInWithAppleButton

 

이 구조체를 사용해서 쉽게 구현할 수 있다

import SwiftUI
import AuthenticationServices

struct SignInView: View {
    var body: some View {
        SignInWithAppleButton(.signUp) { request in
            request.requestedScopes = [.fullName, .email]
        } onCompletion: { result in
            switch result {
            case .success(let authorization):
                handleSuccessfulLogin(with: authorization)
            case .failure(let error):
                handleLoginError(with: error)
            }
        }
        .frame(height: 50)
        .padding()
        
    }
    
    private func handleSuccessfulLogin(with authorization: ASAuthorization) {
        if let userCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            print(userCredential.user)
            
            if userCredential.authorizedScopes.contains(.fullName) {
                print(userCredential.fullName?.givenName ?? "No given name")
            }
            
            if userCredential.authorizedScopes.contains(.email) {
                print(userCredential.email ?? "No email")
            }
        }
    }
    
    private func handleLoginError(with error: Error) {
        print("Could not authenticate: \\(error.localizedDescription)")
    }
}

#Preview {
    SignInView()
}

 

만약 이메일로 로그인을 하게 된다면?

//
//  EmailAuthViewModel.swift
//  Login
//
//  Created by Zizi on 8/22/24.
//

import Foundation
import Combine
import FirebaseAuth
import FirebaseFirestore

class EmailAuthViewModel: ObservableObject, AuthProvider {
    @Published var isAuthenticated: Bool = false
    @Published var errorMessage: String?
    @Published var userDetailInfo: UserDetailInfo?
    @Published var emailErrorMessage: String? = nil
    @Published var passwordErrorMessage: String? = nil
    @Published var nameErrorMessage: String? = nil
    @Published var email: String = "" {
        didSet {
            validateEmailField()
        }
    }
    @Published var password: String = "" {
        didSet {
            validatePasswordField()
        }
    }
    @Published var name: String = "" {
        didSet {
            validateNameField()
        }
    }
    
    func validateEmail(_ email: String) -> Bool {
        let emailPattern = "^[A-Z0-9a-z._%+-]+@[A-Z0-9a-z.-]+\\.[A-Z]{2,}$"
        let regex = try! NSRegularExpression(pattern: emailPattern)
        let result = regex.firstMatch(in: email, range: NSRange(location: 0, length: email.count))
        return result != nil
    }
    
    func validatePassword(_ password: String) -> Bool {
        return password.count >= 8 && password.count <= 16 &&
        password.rangeOfCharacter(from: .uppercaseLetters) != nil &&
        password.rangeOfCharacter(from: .uppercaseLetters) != nil &&
        password.rangeOfCharacter(from: .decimalDigits) != nil
    }
    
    func validateEmailField() {
        if !validateEmail(email) {
            emailErrorMessage = "Invalid email format."
        } else {
            emailErrorMessage = nil
        }
    }
    
    func validatePasswordField() -> String {
        if !validatePassword(password) {
            passwordErrorMessage = "Password must be at least 8 characters long."
        } else {
            passwordErrorMessage = nil
        }
        return "Password must be at least 8 characters long."
    }
    
    func validateName(_ name: String) -> Bool {
        return !name.isEmpty
    }
    
    func validateInputs() -> Bool {
        return validateEmail(email) && validatePassword(password)
    }
    
    func validateNameField() {
        if !validateName(name) {
            nameErrorMessage = "Name cannot be empty."
        } else {
            nameErrorMessage = nil
        }
    }
    
    func signIn() {
        guard validateInputs() else {
            return
        }
        let userInfo = UserInfo(
            email: email,
            isAnonnymous: false,
            authType: [.email],
            name: "User Name",
            password: password
        )
        let userDetailInfo = UserDetailInfo(
            userInfo: userInfo,
            website: "https://example.com",
            phoneNumber: "010-1234-5678",
            birthday: Date(),
            gender: .male
        )
        
        self.userDetailInfo = userDetailInfo
        self.isAuthenticated = true
    }
    
    func signOut() {
        do {
            try Auth.auth().signOut()
            self.isAuthenticated = false
            self.userDetailInfo = nil
        } catch {
            self.errorMessage = "Failed to sign out: \(error.localizedDescription)"
        }
    }
    
    
}

 

import SwiftUI

struct SignUpView: View {
    @ObservedObject var emailAuthViewModel: EmailAuthViewModel
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Sign Up")
                .font(.largeTitle)
                .bold()
            
            TextField("Name", text: $emailAuthViewModel.name)
                .padding()
                .background(Color(.secondarySystemBackground))
                .cornerRadius(5)
                
            
            if let nameError = emailAuthViewModel.nameErrorMessage {
                Text(nameError)
                    .foregroundColor(.red)
                    .font(.footnote)
                    .frame(maxWidth: .infinity, alignment: .leading)
            }
            
            TextField("Email", text: $emailAuthViewModel.email)
                .autocapitalization(.none)
                .keyboardType(.emailAddress)
                .padding()
                .background(Color(.secondarySystemBackground))
                .cornerRadius(5)
            
            if let emailError = emailAuthViewModel.emailErrorMessage {
                Text(emailError)
                    .foregroundColor(.red)
                    .font(.footnote)
                    .frame(maxWidth: .infinity, alignment: .leading)
            }
            
            SecureField("Password", text: $emailAuthViewModel.password)
                .padding()
                .background(Color(.secondarySystemBackground))
                .cornerRadius(5)
            
            if let passwordError = emailAuthViewModel.passwordErrorMessage {
                Text(passwordError)
                    .foregroundColor(.red)
                    .font(.footnote)
                    .frame(maxWidth: .infinity, alignment: .leading)
            }
            
            Button(action: {
                emailAuthViewModel.signIn()
            }) {
                Text("Sign Up")
                    .foregroundColor(.white)
                    .frame(width: 200, height: 50)
                    .background(Color.blue)
                    .cornerRadius(8)
            }
            
            Spacer()
        }
        .padding()
    }
}

struct SignUpView_Previews: PreviewProvider {
    static var previews: some View {
        SignUpView(emailAuthViewModel: EmailAuthViewModel())
    }
}

 

 

반응형