Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#13] 코디네이터 패턴 재설계 및 로그아웃 플로우 시 일부 인스턴스가 해제되지 않는 버그 수정 #15

Merged
merged 5 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions MyLuxury/MyLuxury/App/AppComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,58 @@ import Data
import Domain
import Presentation

typealias CoordinatorDependency = AppCoordinatorDependency & LoginCoordinatorDependency & TabBarCoordinatorDependency & HomeCoordinatorDependency & SearchCoordinatorDependency & LibraryCoordinatorDependency
typealias CoordinatorDependency = AppCoordinatorDependency & LoginCoordinatorDependency & TabBarCoordinatorDependency & HomeCoordinatorDependency & SearchCoordinatorDependency & LibraryCoordinatorDependency & PostCoordinatorDependency

public class AppComponent: CoordinatorDependency {
var navigationController: UINavigationController
var window: UIWindow
public let memberRepository: MemberRepository
public let postRepository: PostRepository
public let memberUseCase: MemberUseCase
public let postUseCase: PostUseCase
public lazy var loginCoordinator: Coordinator = LoginCoordinatorImpl(navigationController: navigationController, dependency: self)
public lazy var tabBarCoordinator: Coordinator = TabBarCoordinatorImpl(navigationController: navigationController, dependency: self)
public lazy var appCoordinator: Coordinator = AppCoordinator(navigationController: self.navigationController, dependency: self)
public lazy var homeCoordinator: Coordinator = HomeCoordinatorImpl(navigationController: self.navigationController, dependency: self)
public lazy var searchCoordinator: Coordinator = SearchCoordinatorImpl(navigationController: self.navigationController, dependency: self)
public lazy var libraryCoordinator: Coordinator = LibraryCoordinatorImpl(navigationController: self.navigationController, dependency: self)
public lazy var appCoordinator: AppCoordinator = AppCoordinatorImpl(dependency: self, window: window)

/// 다른 인스턴스로 실행하고 싶다면 이 생성자에서 해당하는 인스턴스로 바꿔주시면 됩니다.
public init(navigationController: UINavigationController) {
public var loginCoordinator: LoginCoordinator {
get {
return LoginCoordinatorImpl(dependency: self)
}
}

public var tabBarCoordinator: TabBarCoordinator {
get {
return TabBarCoordinatorImpl(dependency: self)
}
}

public var homeCoordinator: HomeCoordinator {
get {
return HomeCoordinatorImpl(dependency: self)
}
}

public var searchCoordinator: SearchCoordinator {
get {
return SearchCoordinatorImpl(dependency: self)
}
}

public var libraryCoordinator: LibraryCoordinator {
get {
return LibraryCoordinatorImpl(dependency: self)
}
}

public var postCoordinator: PostCoordinator {
get {
return PostCoordinatorImpl(dependency: self)
}
}

public init(window: UIWindow) {
print("AppComponent init")
self.navigationController = navigationController
self.window = window
self.memberRepository = MemberRepositoryImpl()
self.postRepository = PostRepositoryMockImpl()
self.memberUseCase = MemberUseCaseImpl(memberRepository: self.memberRepository)
self.postUseCase = PostUseCaseImpl(postRepository: self.postRepository)
self.postRepository = PostRepositoryImpl()
self.memberUseCase = MemberUseCaseImpl(memberRepository: memberRepository)
self.postUseCase = PostUseCaseImpl(postRepository: postRepository)
}
}
7 changes: 2 additions & 5 deletions MyLuxury/MyLuxury/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let splashView = SplashView(window: window!) {
let navigationController = UINavigationController()
navigationController.navigationBar.isHidden = true
self.window?.rootViewController = navigationController
self.appComponent = AppComponent(navigationController: navigationController)
self.appComponent?.appCoordinator.start()
self.appComponent = AppComponent(window: self.window!)
self.window?.rootViewController = self.appComponent?.appCoordinator.start()
}
self.window?.addSubview(splashView)
self.window?.makeKeyAndVisible()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// AppCoordinator.swift
// MyLuxury
//
// Created by KoSungmin on 10/16/24.
//

import UIKit
import AuthenticationServices
import FirebaseAuth

/// 코디네이터는 앱 컴포넌트에서 생성하는 것이기 때문에
/// 앱의 생명주기 내에서 사라지지 않음.

@MainActor
public protocol Coordinator: AnyObject { }

@MainActor
public protocol AppCoordinatorDependency {
var loginCoordinator: LoginCoordinator { get }
var tabBarCoordinator: TabBarCoordinator { get }
}

public protocol AppCoordinator: Coordinator {
var window: UIWindow { get set }
func start() -> UIViewController
}

public class AppCoordinatorImpl: AppCoordinator, LoginCoordinatorDelegate, TabBarCoordinatorDelegate {
public var window: UIWindow
public let dependency: AppCoordinatorDependency
public var childCoordinators: [Coordinator] = []

public init(dependency: AppCoordinatorDependency, window: UIWindow) {
print("AppCoordinator init")
self.dependency = dependency
self.window = window
}

public func start() -> UIViewController {
if let _ = Auth.auth().currentUser {
return showMainFlow()
} else {
return showLoginFlow()
}
}

private func showMainFlow() -> UIViewController {
print("메인 플로우 실행")
let tabBarCoordinator = self.dependency.tabBarCoordinator
tabBarCoordinator.delegate = self
self.childCoordinators.append(tabBarCoordinator)
return tabBarCoordinator.start()
}

private func showLoginFlow() -> UIViewController {
print("로그인 플로우 실행")
let loginCoordinator = self.dependency.loginCoordinator
loginCoordinator.delegate = self
self.childCoordinators.append(loginCoordinator)
return loginCoordinator.start()
}

public func didLogin(_ coordinator: LoginCoordinator) {
self.childCoordinators = self.childCoordinators.filter { $0 !== coordinator }
self.window.rootViewController = showMainFlow()
}

public func didLogout(_ coordinator: TabBarCoordinator) {
self.childCoordinators = self.childCoordinators.filter { $0 !== coordinator }
self.window.rootViewController = showLoginFlow()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import UIKit
import Domain

@MainActor
protocol LoginCoordinator: Coordinator {
public protocol LoginCoordinator: Coordinator {
var delegate: LoginCoordinatorDelegate? { get set }
func start() -> UIViewController
}

@MainActor
protocol LoginCoordinatorDelegate: AnyObject {
public protocol LoginCoordinatorDelegate: AnyObject {
func didLogin(_ coordinator: LoginCoordinator)
}

Expand All @@ -24,26 +25,19 @@ public protocol LoginCoordinatorDependency {
}

public class LoginCoordinatorImpl: LoginCoordinator, @preconcurrency LoginViewControllerDelegate {
public var navigationController: UINavigationController
public var childCoordinators: [Coordinator] = []
public let dependency: LoginCoordinatorDependency
weak var delegate: LoginCoordinatorDelegate?
public weak var delegate: LoginCoordinatorDelegate?
private let dependency: LoginCoordinatorDependency

public init(navigationController: UINavigationController, dependency: LoginCoordinatorDependency) {
public init(dependency: LoginCoordinatorDependency) {
print("LoginCoordinator init")
self.navigationController = navigationController
self.dependency = dependency
}

deinit {
print("LoginCoordinator deinit")
}

public func start() {
public func start() -> UIViewController {
let loginVM = LoginViewModel(memberUseCase: self.dependency.memberUseCase)
let loginVC = LoginViewController(loginVM: loginVM)
loginVC.delegate = self
self.navigationController.viewControllers = [loginVC]
return loginVC
}

@MainActor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ protocol LoginViewControllerDelegate: AnyObject {
func login()
}

class LoginViewController: UIViewController {
public class LoginViewController: UIViewController {
private let rootView: LoginView

weak var delegate: LoginViewControllerDelegate?
Expand All @@ -35,11 +35,11 @@ class LoginViewController: UIViewController {
print("LoginViewController deinit")
}

override func loadView() {
public override func loadView() {
self.view = rootView
}

override func viewDidLoad() {
public override func viewDidLoad() {
super.viewDidLoad()
bindData()
}
Expand Down Expand Up @@ -68,7 +68,7 @@ class LoginViewController: UIViewController {
}

extension LoginViewController: ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
public func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return view.window!
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// TabBarCoordinator.swift
// MyLuxury
//
// Created by KoSungmin on 10/16/24.
//

import UIKit
import Combine

@MainActor
public protocol TabBarCoordinator: Coordinator {
var delegate: TabBarCoordinatorDelegate? { get set }
func start() -> UIViewController
}

@MainActor
public protocol TabBarCoordinatorDelegate: AnyObject {
func didLogout(_ coordinator: TabBarCoordinator)
}

@MainActor
public protocol TabBarCoordinatorDependency {
var homeCoordinator: HomeCoordinator { get }
var searchCoordinator: SearchCoordinator { get }
var libraryCoordinator: LibraryCoordinator { get }
}

public class TabBarCoordinatorImpl: TabBarCoordinator, @preconcurrency LibraryCoordinatorDelegate {
public weak var delegate: TabBarCoordinatorDelegate?
private var dependency: TabBarCoordinatorDependency
var childCoordinators: [Coordinator] = []

public init(dependency: TabBarCoordinatorDependency) {
print("TabBarCoordinatorImpl init")
self.dependency = dependency
}

public func start() -> UIViewController {
let tabBarController = UITabBarController()
tabBarController.tabBar.tintColor = .white
let homeCoordinator = self.dependency.homeCoordinator
let searchCoordinator = self.dependency.searchCoordinator
let libraryCoordinator = self.dependency.libraryCoordinator
childCoordinators.append(homeCoordinator)
childCoordinators.append(searchCoordinator)
childCoordinators.append(libraryCoordinator)
libraryCoordinator.delegate = self
tabBarController.viewControllers = [
homeCoordinator.start(),
searchCoordinator.start(),
libraryCoordinator.start()
]
return tabBarController
}

@MainActor
public func logout() {
NotificationCenter.default.post(name: .didLogout, object: nil)
self.childCoordinators.removeAll()
self.delegate?.didLogout(self)
}
}

This file was deleted.

Loading
Loading