import SwiftUI
import Firebase
@main
struct SwiftfulFirebaseApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
print("Firebase Configured")
return true
}
}
Firebase초기 설정!
init구문에서 FirebaseApp.configure를 해줘도 되고
지금처럼 AppDelegate 만들고 추가해줘도 됨
로그인은 FirebaseAuth 패키지가 설치되야한다
tutorial엔 Firebase Core를 임포트 해주라고 나오는데
import Firebase 로 충분함

AuthenticationView 라는 간단한 뷰를 구성해줌

위에 버튼 누르면 네비게이션 되는 Email이랑 비밀번호 입력하는 뷰도 뷰모델도 구성해줌
(비밀번호는 SecureField로 만들 수 있구나!)
Auth에 관한 매니저를 만들어서 뷰와 뷰모델과는 별개로 사용할 수 있게 해주자! 이러면 다른 앱에서도 사용해볼 수 있겠죠
import Foundation
import FirebaseAuth
final class AuthenticationManager {
static let shared = AuthenticationManager()
private init() { }
func createUser(email: String, password: String) async throws {
let authDataResult = try await Auth.auth().createUser(withEmail: email, password: password)
}
}
createUser를 하는
authDataResult의 타입은 AuthDataResult타입인데 Firebase에서 만들어진 타입임!
이걸 사용하는 것보다 우리가 모델 만들어서 넣어주는 게 좋을 것 같습니다

import Foundation
import FirebaseAuth
struct AuthDataResultModel {
let uid: String
let email: String?
let photoUrl: String?
init(user: User) {
self.uid = user.uid
self.email = user.email
self.photoUrl = user.photoURL?.absoluteString
}
}
final class AuthenticationManager {
static let shared = AuthenticationManager()
private init() { }
func createUser(email: String, password: String) async throws -> AuthDataResultModel {
let authDataResult = try await Auth.auth().createUser(withEmail: email, password: password)
return AuthDataResultModel(user: authDataResult.user)
}
}
AuthDataResultModel을 만들어주고 init될 때 User를 받아서 넘겨주는 model을 구성, createUser의 반환 값으로 AuthDataResultModel이 반환되게 해줌
SignInEmailViewModel로 돌아와서
@MainActor
final class SignInEmailViewModel: ObservableObject {
@Published var email = ""
@Published var password = ""
func signIn() {
guard !email.isEmpty, !password.isEmpty else {
print("No email or password found")
return
}
Task {
do {
let returnedUserData = try await AuthenticationManager.shared.createUser(email: email, password: password)
print("Success")
print(returnedUserData)
} catch {
print("error: \(error)")
}
}
}
}
signIn 메소드를 작성해줬다!
가드문으로 필드가 비었을 때 막아주고
Task로 do catch 구문에서 Success 와 Error일 때 작성해줌

그리고 버튼 누를 때 SignIn되게 해주면


User가 생성되었습니다~!
RootView를 만들어줌


getAuthenticatedUser 메소드를 만들어줬는데
Auth.auth().currentUser 메소드로 로그인한 정보가 가져와지나봄




signOut도 가능하게 해줌
AuthenticationManager에서 User타입을 인지 못해서 import Firebase도 해줬음!
RootView에서 showSignInView 불 값에 따라서
AuthenticationView를 띄워주개 되는데
SettingsView에도 이 Bool값이 바인딩 되어 있고(로그아웃 했을 때)
AuthenticationView의 하위 SignInEmailView에도 이 값이 바인딩 되어 있다!
로그인 하면 false로 바뀌고 RootView가 떠야하니까!
그리고 지금 당장은 signIn메소드 내에서 사용하는 returnedUserData를 어딘가에서 사용하고 있지않음! 이럴 때 @discardableResult를 붙여주면 됩니다
(그리고 let returnedUserData는 지워줘도됨)

viewModel의 signIn메소드는 요렇게 Task안에서 do catch로 처리가 되고 !
지금 SignIn을 하게 될 땐 createUser만 해주고 있어서
이미 있는 유저 계정으로 로그인할 땐 로그인이 안되고 있음

AuthManager에서 SignInUser 메소드를 만들어주고!

기존에 있던 메소드는 signUp으로 네이밍 해주고
아래에 새로운 signIn메소드를 구성해줬음

그리고 버튼내에서 signUp이 성공했을 때 Return 으로 빠져나오게 해줘서 signUp을 성공하면 아래의 signIn메소드가 실행되지 않게 해줬다!
password Reset도 구현해봅시다

AuthenticationManager에서 메소드를 구현해줬다

authUser를 가져와서 authUser의 email을 가지고 resetPassword가 가능해지게 해줌


보내는 메일의 형식은 여기서 바꿔줄 수 있음!
자세히 알아보기 클릭해서 들어가면 어떻게 바꿀지 보임
(사실은 Settings page가서 바꿔줘야됩니다~)

AuthenticationManager에서 update하는 메소드도 구현해줌
SettingsViewModel에서 방금 작성한애들이 들어간 메소드 작성해주고!
이제 업데이트도 가능해졌습니다~!
(업데이트 할려면 다시 로그인 해줘야지 가능함)