From 12abbe7e6ea257fa1686a2ef24fbf12009adcb8d Mon Sep 17 00:00:00 2001 From: Nicholas Tay Date: Mon, 21 Mar 2022 15:13:23 +1100 Subject: First try at implementing coordinator pattern Resources: - https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps --- foray.xcodeproj/project.pbxproj | 8 ++++++ foray/AppDelegate.swift | 13 +++++---- foray/Coordinator.swift | 19 +++++++++++++ foray/ForayCoordinator.swift | 53 +++++++++++++++++++++++++++++++++++ foray/ForayDetailViewController.swift | 26 +++++------------ foray/ForayTableViewController.swift | 10 +++---- 6 files changed, 98 insertions(+), 31 deletions(-) create mode 100644 foray/Coordinator.swift create mode 100644 foray/ForayCoordinator.swift diff --git a/foray.xcodeproj/project.pbxproj b/foray.xcodeproj/project.pbxproj index 066c2b1..b0a62f6 100644 --- a/foray.xcodeproj/project.pbxproj +++ b/foray.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ C011E4F127E6211400C248D6 /* ForayNetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C011E4F027E6211400C248D6 /* ForayNetworkManager.swift */; }; C011E4F327E6216C00C248D6 /* ForayItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = C011E4F227E6216C00C248D6 /* ForayItems.swift */; }; + C049BBFE27E82B9E003820A9 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C049BBFD27E82B9E003820A9 /* Coordinator.swift */; }; + C049BC0027E82C90003820A9 /* ForayCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C049BBFF27E82C90003820A9 /* ForayCoordinator.swift */; }; C04B45A427DEF117001451A3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04B45A327DEF117001451A3 /* AppDelegate.swift */; }; C04B45A627DEF117001451A3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04B45A527DEF117001451A3 /* SceneDelegate.swift */; }; C04B45AD27DEF118001451A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C04B45AC27DEF118001451A3 /* Assets.xcassets */; }; @@ -21,6 +23,8 @@ /* Begin PBXFileReference section */ C011E4F027E6211400C248D6 /* ForayNetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForayNetworkManager.swift; sourceTree = ""; }; C011E4F227E6216C00C248D6 /* ForayItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForayItems.swift; sourceTree = ""; }; + C049BBFD27E82B9E003820A9 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; + C049BBFF27E82C90003820A9 /* ForayCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForayCoordinator.swift; sourceTree = ""; }; C04B45A027DEF117001451A3 /* foray.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = foray.app; sourceTree = BUILT_PRODUCTS_DIR; }; C04B45A327DEF117001451A3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C04B45A527DEF117001451A3 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -71,6 +75,8 @@ C011E4F027E6211400C248D6 /* ForayNetworkManager.swift */, C04B45AC27DEF118001451A3 /* Assets.xcassets */, C04B45B127DEF118001451A3 /* Info.plist */, + C049BBFD27E82B9E003820A9 /* Coordinator.swift */, + C049BBFF27E82C90003820A9 /* ForayCoordinator.swift */, ); path = foray; sourceTree = ""; @@ -150,7 +156,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C049BBFE27E82B9E003820A9 /* Coordinator.swift in Sources */, C011E4F127E6211400C248D6 /* ForayNetworkManager.swift in Sources */, + C049BC0027E82C90003820A9 /* ForayCoordinator.swift in Sources */, C04B45B827DEF2ED001451A3 /* ForayTableViewController.swift in Sources */, C0FEAF5F27E14C52000A7648 /* ForayDetailViewController.swift in Sources */, C04EDE4427E4298D00D83005 /* ForayNewTableViewCell.swift in Sources */, diff --git a/foray/AppDelegate.swift b/foray/AppDelegate.swift index fc5d2f9..7795d22 100644 --- a/foray/AppDelegate.swift +++ b/foray/AppDelegate.swift @@ -11,17 +11,18 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? + var coordinator: Coordinator? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let nav = UINavigationController() - let mainView = ForayTableViewController() - nav.viewControllers = [mainView] - let window = UIWindow(frame: UIScreen.main.bounds) - window.rootViewController = nav - self.window = window - window.makeKeyAndVisible() + coordinator = ForayCoordinator(navigationController: nav) + coordinator?.start() + + self.window = UIWindow(frame: UIScreen.main.bounds) + self.window?.rootViewController = nav + self.window?.makeKeyAndVisible() return true } diff --git a/foray/Coordinator.swift b/foray/Coordinator.swift new file mode 100644 index 0000000..db97a1d --- /dev/null +++ b/foray/Coordinator.swift @@ -0,0 +1,19 @@ +// +// Coordinator.swift +// foray +// +// Created by Nicholas Tay on 21/3/2022. +// Based on code from Paul Hudson on Hacking with Swift +// (https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps) +// + +import Foundation +import UIKit + +protocol Coordinator { + var childCoordinators: [Coordinator] { get set } + var navigationController: UINavigationController { get set } + + func start() +} + diff --git a/foray/ForayCoordinator.swift b/foray/ForayCoordinator.swift new file mode 100644 index 0000000..8fe6656 --- /dev/null +++ b/foray/ForayCoordinator.swift @@ -0,0 +1,53 @@ +// +// ForayCoordinator.swift +// foray +// +// Created by Nicholas Tay on 21/3/2022. +// + +import Foundation +import UIKit + +protocol ForayCoordinated: UIViewController { + var coordinator: ForayCoordinator? { get set } +} + +class ForayCoordinator: Coordinator { + var childCoordinators = [Coordinator]() + var navigationController: UINavigationController + + init(navigationController: UINavigationController) { + self.navigationController = navigationController + } + + private func push(vc: ForayCoordinated, animated: Bool = true) { + vc.coordinator = self + navigationController.pushViewController(vc, animated: animated) + } + + func start() { + push(vc: ForayTableViewController(), animated: false) + } + + let detailViewController = ForayDetailViewController() + + func showDetails(item: PenguinItem) { + let image: UIImage + var description: String = "Type: " + switch item.type { + case .item: + description += "Item" + image = UIImage(named: item.id)! + case .quest: + description += "Quest" + image = UIImage(named: "spy")! + } + description += "\nID: " + item.id + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + description += "\nReleased: " + dateFormatter.string(from: item.releaseDate) + + detailViewController.setDetails(name: item.name, description: description, image: image) + push(vc: detailViewController) + } +} diff --git a/foray/ForayDetailViewController.swift b/foray/ForayDetailViewController.swift index 08845df..1382d24 100644 --- a/foray/ForayDetailViewController.swift +++ b/foray/ForayDetailViewController.swift @@ -7,7 +7,9 @@ import UIKit -class ForayDetailViewController: UIViewController { +class ForayDetailViewController: UIViewController, ForayCoordinated { + + var coordinator: ForayCoordinator? let scrollView: UIScrollView = { let sv = UIScrollView() @@ -83,24 +85,10 @@ class ForayDetailViewController: UIViewController { } } - public func setSelectedItem(selectedItem: PenguinItem) { - nameLabel.text = selectedItem.name - itemImageView.image = UIImage(named: selectedItem.id) - - descLabel.text = "Type: " - switch selectedItem.type { - case .item: - descLabel.text! += "Item" - case .quest: - descLabel.text! += "Quest" - itemImageView.image = UIImage(named: "spy") - } - - descLabel.text! += "\nID: " + selectedItem.id - - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd" - descLabel.text! += "\nReleased: " + dateFormatter.string(from: selectedItem.releaseDate) + public func setDetails(name: String, description: String, image: UIImage) { + nameLabel.text = name + descLabel.text = description + itemImageView.image = image } } diff --git a/foray/ForayTableViewController.swift b/foray/ForayTableViewController.swift index 2732fce..827d4ea 100644 --- a/foray/ForayTableViewController.swift +++ b/foray/ForayTableViewController.swift @@ -13,7 +13,9 @@ private func firstDayOfYear(date: Date) -> Date { return calendar.date(from: components)! } -class ForayTableViewController: UITableViewController { +class ForayTableViewController: UITableViewController, ForayCoordinated { + + var coordinator: ForayCoordinator? // MARK: - Static data TEMP @@ -110,14 +112,10 @@ class ForayTableViewController: UITableViewController { return "Released in " + dateFormatter.string(from: section.year) } - let detailViewController: ForayDetailViewController = ForayDetailViewController() - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let item = self.sections[indexPath.section].items[indexPath.row] - detailViewController.setSelectedItem(selectedItem: item) - - self.navigationController?.pushViewController(detailViewController, animated: true) + self.coordinator?.showDetails(item: item) } } -- cgit