✅ 현재 코드의 흐름
📌 회원가입 성공 시
- RegisterViewController에서 회원가입이 성공하면 현재 띄워진 모든 모달을 닫음 (dismiss())
- NotificationCenter를 사용해 SceneDelegate에게 회원가입 성공을 알림 (CreateUserSuccess)
- SceneDelegate에서 checkAuthentication() 실행
- checkAuthentication()에서 window?.rootViewController를 MainTabBarController로 변경
✔️ 지금 코드의 장점
✅ 앱의 전체적인 화면 이동을 SceneDelegate에서 관리해서 중앙 집중식 제어 가능
✅ NotificationCenter를 사용해 뷰 컨트롤러 간 의존성을 줄임
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
self.setupWindow(with: scene)
checkAuthentication()
// ✅ 로그아웃 시 화면 변경을 위한 Notifiation 설정
NotificationCenter.default.addObserver(self, selector: #selector(handleLogout), name: NSNotification.Name("UserDidLogout"), object: nil)
// 회원가입 성공 후 처리
NotificationCenter.default.addObserver(self, selector: #selector(handleUserCreated), name: NSNotification.Name("CreateUserSuccess"), object: nil)
}
@objc private func handleLogout() {
checkAuthentication()
}
@objc private func handleUserCreated() {
checkAuthentication()
}
private func setupWindow(with scene: UIScene) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
self.window = window
self.window?.makeKeyAndVisible()
}
public func checkAuthentication() {
if Auth.auth().currentUser == nil {
self.gotoController(with: UINavigationController(rootViewController: OnboardingViewController()))
} else {
// ✅ 기존에 MainTabBarController가 있으면 새로 만들지 않음
if !(window?.rootViewController is MainTabBarController) {
gotoController(with: MainTabBarController())
}
}
}
private func gotoController(with viewController: UIViewController) {
DispatchQueue.main.async { [weak self] in
UIView.animate(withDuration: 0.3) {
self?.window?.layer.opacity = 0
} completion: { [weak self] _ in
let vc = viewController
vc.modalPresentationStyle = .fullScreen
self?.window?.rootViewController = vc
UIView.animate(withDuration: 0.3) {
self?.window?.layer.opacity = 1
}
}
}
}
}
// ✅ MARK: - RegisterViewController
class RegisterViewController: UIViewController {
...
private func bindViews() {
emailTextField.addTarget(self, action: #selector(didChangedEmailField), for: .editingChanged)
passwordTextField.addTarget(self, action: #selector(didChangedPassword), for: .editingChanged)
registerButton.addTarget(self, action: #selector(didTapRegister), for: .touchUpInside)
viewModel.$isAuthenticationFormValid
.sink { [weak self] validationState in
self?.registerButton.isEnabled = validationState
}
.store(in: &cancelable)
// ✅ 회원가입 성공에 따른 화면 이동
viewModel.$user
.sink { [weak self] user in
guard user != nil else { return }
// ✅ 현재 창에서 띄워진 모든 모달을 닫음 (OnboardingViewController 포함)
self?.view.window?.rootViewController?.dismiss(animated: true)
// SceneDelegate에게 알림
NotificationCenter.default.post(name: NSNotification.Name("CreateUserSuccess"), object: nil)
}
.store(in: &cancelable)
}
❌ 하지만 현재 코드의 문제점
- 불필요한 checkAuthentication() 호출
- 이미 회원가입을 완료했으면, Auth.auth().currentUser는 무조건 존재하는 상태
- 그런데 다시 checkAuthentication()을 실행해서 gotoController(MainTabBarController())을 호출함
- 즉, 화면을 이동할 필요가 없는데도 강제로 rootViewController를 바꾸고 있음
- 회원가입 후 모든 화면을 닫은 뒤 SceneDelegate를 다시 부를 필요가 없음
- self?.view.window?.rootViewController?.dismiss(animated: true) → 이 코드가 이미 모든 모달을 닫고 있음
- 즉, MainTabBarController가 이미 rootViewController라면 그대로 두는 것이 더 효율적임
- NotificationCenter를 통해 굳이 알림을 보낼 필요가 없음
🔹 1. RegisterViewController에서 직접 rootViewController 변경
굳이 NotificationCenter를 사용하지 않고, SceneDelegate를 호출하지 않아도 됨.
회원가입이 성공하면 바로 window?.rootViewController = MainTabBarController()를 설정하면 끝!
viewModel.$user
.sink { [weak self] user in
guard user != nil else { return }
// 현재 RegisterViewController가 띄워진 모든 모달을 닫음 (Onboarding 포함)
self?.view.window?.rootViewController?.dismiss(animated: true, completion: {
// ✅ 모든 화면을 닫은 후, rootViewController를 변경 (MainTabBarController로)
if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
sceneDelegate.window?.rootViewController = MainTabBarController()
}
})
}
.store(in: &cancelable)
✔️ 이렇게 하면 checkAuthentication()을 호출하지 않고도 바로 화면 전환이 가능
✔️ 불필요한 NotificationCenter 호출 없이 UI가 즉시 변경됨
✔️ 회원가입 후 자연스럽게 MainTabBarController로 이동함
🔹 2. SceneDelegate는 로그인 상태 확인용으로만 사용
회원가입이 성공하면 현재 띄워진 모든 화면을 닫은 후, MainTabBarController를 설정
회원가입 완료 후에는 SceneDelegate를 다시 호출할 필요가 없음
대신, 앱이 처음 실행될 때만 checkAuthentication()을 실행해서 초기 화면을 설정하는 게 좋음.
viewModel.$user
.sink { [weak self] user in
guard user != nil else { return }
// 현재 RegisterViewController가 띄워진 모든 모달을 닫음 (Onboarding 포함)
self?.view.window?.rootViewController?.dismiss(animated: true, completion: {
// ✅ 모든 화면을 닫은 후, rootViewController를 변경 (MainTabBarController로)
if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
sceneDelegate.window?.rootViewController = MainTabBarController()
}
})
}
.store(in: &cancelable)
🔹 로그아웃 과정도 동일하게..
로그아웃 후 불필요한 NotificationCenter 호출 없이 바로 OnboardingViewController로 이동
@objc private func didTapSignOut() {
do {
try Auth.auth().signOut()
// ✅ 현재 모든 화면을 닫은 후, OnboardingViewController로 이동
self.view.window?.rootViewController?.dismiss(animated: true, completion: {
if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
sceneDelegate.window?.rootViewController = UINavigationController(rootViewController: OnboardingViewController())
}
})
} catch {
print("로그아웃 실패: \(error.localizedDescription)")
}
}
🚀 최종 정리
✅ 회원가입 시 → rootViewController = MainTabBarController()
✅ 로그아웃 시 → rootViewController = OnboardingViewController()
✅ 불필요한 NotificationCenter 제거
🚀 로그아웃 시 기존 MainTabBarController를 남기지 않고 완전히 제거하는 방식 - 추천
✔️ 로그아웃하면 기존의 모든 화면을 제거하고, 새로 OnboardingViewController로 이동
✔️ 새로운 유저가 로그인하면 새로운 MainTabBarController를 생성 → 깨끗한 상태 유지
✔️ 불필요한 메모리 사용을 방지 (이전 유저의 데이터가 남지 않음)
'Project > MovieClip' 카테고리의 다른 글
👤 Firebase에 로그인, 회원정보를 FireStore 저장, 회원정보 불러오기 (0) | 2025.02.27 |
---|---|
👤 Firebase에 이메일 & 비밀번호 회원가입 기능 (MVVM + Combine) (0) | 2025.02.26 |
❌ 문제 해결 - 검색 결과의 상세페이지 이동이 안됨.. (0) | 2025.02.24 |
🔨 검색결과 내의 영화, 티비의 장르 가져오는 부분 개선 (0) | 2025.02.24 |
🔥 MVVM + Combine을 통한 검색기능 구현 2편 구현 순서? (0) | 2025.02.24 |