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

Router를 정의했습니다. #17

Merged
merged 9 commits into from
Jul 23, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,9 @@ extension RecipeDetailViewController: RecipeDetailInteractorDelegate {
}
}
}

extension RecipeDetailViewController: Drawable {
var viewController: UIViewController? {
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ final class RecipeListView: UIView {
private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

private var recipes: [RecipeListItemViewModel] = []
weak var coordinator: RecipeDetailCoordinatorProtocol?
weak var delegate: RecipeListViewDelegate?

override init(frame: CGRect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ final class RecipeListViewController: UIViewController {
private var recipes: [RecipeListItemViewModel] = []
private let searchBar = SearchBar()
private let recipeListView = RecipeListView()

init(interactor: RecipeListInteractor) {
self.interactor = interactor
super.init(nibName: nil, bundle: nil)
private let recipeListMapper = RecipeListMapper()
private let router: RecipeListRouter

init(interactor: RecipeListInteractor, router: RecipeListRouter) {
self.interactor.setDelegate(self)

self.interactor = interactor
self.router = router
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
Expand Down Expand Up @@ -90,7 +92,7 @@ extension RecipeListViewController: RecipeListInteractorDelegate {
}

func showRecipeDetail(ID: Int) {
coordinator.showRecipeDetail(from: self, recipeID: ID)
router.navigateToRecipeDetail(from: self, recipeID: ID)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ class MainTabBarController: UITabBarController, UITabBarControllerDelegate {

private let addButton = UIButton(type: .custom)
private let buttonSize = CGSize(all: 64.0)
private let router = Router()

init(router: Router) {
self.router = router
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -33,23 +43,26 @@ class MainTabBarController: UITabBarController, UITabBarControllerDelegate {
}

private func setupTabBar() {
let baseneworkServie = BaseNetworkService()
let networkService = RecipeFetchServiceImpl(networkService: baseneworkServie)
let repository = FeedListRepositoryImpl(networkService: networkService)
let searchrepository = SearchFeedRepositoryImpl(networkService: networkService)
let fetchFeedListUseCase = FetchFeedListUseCaseImpl(repository: repository)
let searchFeedListUsecase = SearchFeedListUseCaseImpl(repository: searchrepository)

let recipeListViewModel = RecipeListInteractor(fetchFeedListUseCase: fetchFeedListUseCase, searchFeedListUseCase: searchFeedListUsecase)

let recipeListVC = RecipeListViewController(interactor: recipeListViewModel)
recipeListVC.tabBarItem = UITabBarItem(title: "Recipes", image: UIImage(systemName: "list.bullet"), tag: 0)
let recipeListVC = router.createRecipeListDependencies()
let favoritesVC = createFavoritesViewController()
recipeListVC.tabBarItem = UITabBarItem(
title: "Recipes",
image: UIImage(systemName: "list.bullet"),
tag: 0
)
favoritesVC.tabBarItem = UITabBarItem(
title: "Favorites",
image: UIImage(systemName: "bookmark"),
tag: 1
)

viewControllers = [recipeListVC, favoritesVC]
}

private func createFavoritesViewController() -> UIViewController {
let favoritesVC = UIViewController()
favoritesVC.view.backgroundColor = .white
favoritesVC.tabBarItem = UITabBarItem(title: "Favorites", image: UIImage(systemName: "bookmark"), tag: 1)

viewControllers = [recipeListVC, favoritesVC]
return favoritesVC
}

private func setupActionButton() {
Expand All @@ -68,12 +81,12 @@ class MainTabBarController: UITabBarController, UITabBarControllerDelegate {
let alert = UIAlertController(title: "게시물 작성", message: "어떤 게시물을 작성하실 건가요?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Coffee", style: .default, handler: { [weak self] _ in
guard let self else { return }
let addRecipeVC = AddRecipeViewController(recipeType: .coffee)
let addRecipeVC = router.makeAddRecipeViewController(recipeType: .coffee)
self.navigationController?.pushViewController(addRecipeVC, animated: true)
}))
alert.addAction(UIAlertAction(title: "Dessert", style: .default, handler: { [weak self] _ in
guard let self else { return }
let addRecipeVC = AddRecipeViewController(recipeType: .dessert)
let addRecipeVC = router.makeAddRecipeViewController(recipeType: .dessert)
self.navigationController?.pushViewController(addRecipeVC, animated: true)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
Expand Down
25 changes: 25 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Router/RecipeListRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RecipeListRouter.swift
// HomeCafeRecipes
//
// Created by 김건호 on 7/9/24.
//

import UIKit

protocol RecipeListRouter {
func navigateToRecipeDetail(from viewController: UIViewController, recipeID: Int)
}

class RecipeListRouterImpl: RecipeListRouter {
private let router: Router

init(router: Router) {
self.router = router
}

func navigateToRecipeDetail(from viewController: UIViewController, recipeID: Int) {
let detailVC = router.makeRecipeDetailViewController(recipeID: recipeID)
router.push(detailVC, from: viewController, isAnimated: true, onNavigateBack: nil)
}
}
108 changes: 108 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Router/Router.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// Router.swift
// HomeCafeRecipes
//
// Created by 김건호 on 7/9/24.
//

import UIKit

public typealias NavigationBackClosure = () -> Void

public protocol Drawable {
var viewController: UIViewController? { get }
}

public protocol RouterProtocol {
func push (
_ drawable: Drawable,
from viewController: UIViewController,
isAnimated: Bool,
onNavigateBack closure: NavigationBackClosure?
)
}

class Router: NSObject, RouterProtocol {
private var closures: [String: NavigationBackClosure] = [:]

func push(
_ drawable: Drawable,
from viewController: UIViewController,
isAnimated: Bool,
onNavigateBack closure: NavigationBackClosure?
) {
guard let targetViewController = drawable.viewController else {
return
}

if let closure = closure {
closures.updateValue(closure, forKey: targetViewController.description)
}
viewController.navigationController?.pushViewController(targetViewController, animated: isAnimated)
}

private func executeClosure(_ viewController: UIViewController) {
guard let closure = closures.removeValue(forKey: viewController.description) else { return }
closure()
}
}

extension Router {
func makeRecipeListViewController() -> RecipeListViewController {
let recipeListInteractor = RecipeListInteractorImpl(
fetchFeedListUseCase: FetchFeedListUseCaseImpl(
repository: FeedListRepositoryImpl(
networkService: RecipeFetchServiceImpl(
networkService: BaseNetworkService()
)
)
),
searchFeedListUseCase: SearchFeedListUseCaseImpl(
repository: SearchFeedRepositoryImpl(
networkService: RecipeFetchServiceImpl(
networkService: BaseNetworkService()
)
)
)
)
let recipeListRouter = RecipeListRouterImpl(router: self)
let recipeListVC = RecipeListViewController(
interactor: recipeListInteractor,
router: recipeListRouter
)
recipeListInteractor.delegate = recipeListVC
return recipeListVC
}

func makeAddRecipeViewController(recipeType: RecipeType) -> AddRecipeViewController {
let addRecipeInteractor = AddRecipeInteractorImpl(
saveRecipeUseCase: AddRecipeUseCaseImpl(
repository: AddRecipeRepositoryImpl(
recipePostService: RecipePostServiceImpl(
networkService: BaseNetworkService()
)
)
)
)
let addRecipeVC = AddRecipeViewController(
recipeType: recipeType,
addRecipeInteractor: addRecipeInteractor
)
addRecipeInteractor.delegate = addRecipeVC
return addRecipeVC
}

func makeRecipeDetailViewController(recipeID: Int) -> RecipeDetailViewController {
let detailInteractor = RecipeDetailInteractorImpl(
fetchRecipeDetailUseCase: FetchRecipeDetailUseCaseImpl(
repository: RecipeDetailRepositoryImpl(
networkService: BaseNetworkService()
)
),
recipeID: recipeID
)
let detailVC = RecipeDetailViewController(interactor: detailInteractor)
detailInteractor.delegate = detailVC
return detailVC
}
}
10 changes: 7 additions & 3 deletions HomeCafeRecipes/HomeCafeRecipes/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

var router: Router?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let mainViewController = ViewController()
let navigationController = UINavigationController(rootViewController : mainViewController)
router = Router()
guard let router else { return }

let tabBarController = MainTabBarController(router: router)
let navigationController = UINavigationController(rootViewController: tabBarController)
navigationController.isNavigationBarHidden = true
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
Expand Down