반응형
회원가입
이메일
이메일 유효성 검사
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())
}
}
반응형
'SwiftUI' 카테고리의 다른 글
SwiftUI | HeaderView(Sticky View)만들기전 알아야할 기본 상식 정의 + 만들기 - 1 (0) | 2024.09.19 |
---|---|
SwiftUI | 프로젝트에서 info.plist가 누락되었을 때 (0) | 2024.08.22 |
SwiftUI | SwiftData Tutorials - List / NavigationStack / DatePicker (0) | 2024.08.08 |
SwiftUI | 다양한 정렬 및 레이아웃(HStack / VStack / ZStack) (0) | 2024.08.07 |
SwiftUI | Hello SwiftUI -2 (1) | 2024.08.07 |