From bd7761216a065b0dd859cb19d709996739a240cd Mon Sep 17 00:00:00 2001 From: Nicholas Tay Date: Sun, 17 Jul 2022 02:25:12 +1000 Subject: Clean up force unwraps and lets Wow, I didn't know `if let` was a thing back then, haha. Also made UIImage a bit safer in case asset is missing by unwrapping in one common place. --- foray.xcodeproj/project.pbxproj | 4 ++++ foray/Extensions/UIImage+Extensions.swift | 21 +++++++++++++++++++++ foray/Fetchers/ForayFetcher.swift | 14 ++++++++------ foray/Presenters/PenguinItemPresenter.swift | 9 +++------ foray/Scenes/ForayDetailViewController.swift | 4 ++-- foray/Scenes/ForayTableViewController.swift | 6 +++--- 6 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 foray/Extensions/UIImage+Extensions.swift diff --git a/foray.xcodeproj/project.pbxproj b/foray.xcodeproj/project.pbxproj index 3901dc6..df040dd 100644 --- a/foray.xcodeproj/project.pbxproj +++ b/foray.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 014E13B128831B6A00C9C353 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014E13B028831B6A00C9C353 /* UIImage+Extensions.swift */; }; C011E4F127E6211400C248D6 /* ForayFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C011E4F027E6211400C248D6 /* ForayFetcher.swift */; }; C011E4F327E6216C00C248D6 /* PenguinItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C011E4F227E6216C00C248D6 /* PenguinItemModel.swift */; }; C049BBFE27E82B9E003820A9 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C049BBFD27E82B9E003820A9 /* Coordinator.swift */; }; @@ -26,6 +27,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 014E13B028831B6A00C9C353 /* UIImage+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = ""; }; C011E4F027E6211400C248D6 /* ForayFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForayFetcher.swift; sourceTree = ""; }; C011E4F227E6216C00C248D6 /* PenguinItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinItemModel.swift; sourceTree = ""; }; C049BBFD27E82B9E003820A9 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; @@ -106,6 +108,7 @@ isa = PBXGroup; children = ( C09676BB27EC27E700353D46 /* UIViewController+Extensions.swift */, + 014E13B028831B6A00C9C353 /* UIImage+Extensions.swift */, ); path = Extensions; sourceTree = ""; @@ -231,6 +234,7 @@ C04B45A427DEF117001451A3 /* AppDelegate.swift in Sources */, C09676BA27E86B6E00353D46 /* ForayLoadingOverlay.swift in Sources */, C011E4F327E6216C00C248D6 /* PenguinItemModel.swift in Sources */, + 014E13B128831B6A00C9C353 /* UIImage+Extensions.swift in Sources */, C0C73E6727EC3BA50015497D /* PenguinItemPresenter.swift in Sources */, C04B45A627DEF117001451A3 /* SceneDelegate.swift in Sources */, ); diff --git a/foray/Extensions/UIImage+Extensions.swift b/foray/Extensions/UIImage+Extensions.swift new file mode 100644 index 0000000..252c3fb --- /dev/null +++ b/foray/Extensions/UIImage+Extensions.swift @@ -0,0 +1,21 @@ +// +// UIImage+Extensions.swift +// foray +// +// Created by Nicholas Tay on 17/7/2022. +// + +import UIKit + +extension UIImage { + static func fromAsset(_ assetImage: AssetImage) -> UIImage { + return UIImage(named: assetImage.rawValue)! + } +} + +/// Known asset images that we can safely unwrap +enum AssetImage: String { + case AppIcon + case it + case spy +} diff --git a/foray/Fetchers/ForayFetcher.swift b/foray/Fetchers/ForayFetcher.swift index e4c6fd9..15db4c1 100644 --- a/foray/Fetchers/ForayFetcher.swift +++ b/foray/Fetchers/ForayFetcher.swift @@ -21,20 +21,22 @@ class ForayFetcher { let dateFormat = DateFormatter() dateFormat.dateFormat = "yyyy-MM-dd" - + + // OK to throw as I believe it just errors out the decode; it isn't what we expected schema wise return dateFormat.date(from: dateStr)! }) return jd }() - func fetch(url: String) async throws -> T { - var request = URLRequest(url: URL(string: url)!) + func fetch(url: URL) async throws -> T { + var request = URLRequest(url: url) request.cachePolicy = .reloadRevalidatingCacheData // Needed otherwise default caching policy seems not to check properly // Basic auth if required - if (self.basicUsername != nil && self.basicPassword != nil) { - let authData = (self.basicUsername! + ":" + self.basicPassword!).data(using: .utf8)!.base64EncodedString() - request.addValue("Basic \(authData)", forHTTPHeaderField: "Authorization") + if let basicUsername = basicUsername, + let basicPassword = basicPassword, + let authData = (basicUsername + ":" + basicPassword).data(using: .utf8) { + request.addValue("Basic \(authData.base64EncodedString())", forHTTPHeaderField: "Authorization") } let (data, _) = try await URLSession.shared.data(for: request) diff --git a/foray/Presenters/PenguinItemPresenter.swift b/foray/Presenters/PenguinItemPresenter.swift index 1d617bf..45b970c 100644 --- a/foray/Presenters/PenguinItemPresenter.swift +++ b/foray/Presenters/PenguinItemPresenter.swift @@ -16,12 +16,9 @@ class PenguinItemPresenter { let fetcher = ForayFetcher() func fetch() async -> [PenguinItemViewModel] { - do { - let apiItems: [PenguinItemModel] = try await fetcher.fetch(url: Constants.apiEndpoint) - return transform(models: apiItems) - } catch { - return [] - } + guard let endpoint = URL(string: Constants.apiEndpoint), + let apiItems: [PenguinItemModel] = try? await fetcher.fetch(url: endpoint) else { return [] } + return transform(models: apiItems) } func transform(models: [PenguinItemModel]) -> [PenguinItemViewModel] { diff --git a/foray/Scenes/ForayDetailViewController.swift b/foray/Scenes/ForayDetailViewController.swift index 1e2f9ca..52aa6b8 100644 --- a/foray/Scenes/ForayDetailViewController.swift +++ b/foray/Scenes/ForayDetailViewController.swift @@ -29,10 +29,10 @@ class ForayDetailViewController: UIViewController, HasCustomView, Coordinated { switch item.type { case .item: description += "Item" - image = UIImage(named: item.id)! + image = UIImage(named: item.id) ?? UIImage.fromAsset(.it) case .quest: description += "Quest" - image = UIImage(named: "spy")! + image = UIImage.fromAsset(.spy) } description += "\nID: " + item.id description += "\nReleased: " + item.releaseDateFormatted diff --git a/foray/Scenes/ForayTableViewController.swift b/foray/Scenes/ForayTableViewController.swift index 849553c..3d839a1 100644 --- a/foray/Scenes/ForayTableViewController.swift +++ b/foray/Scenes/ForayTableViewController.swift @@ -87,13 +87,13 @@ class ForayTableViewController: UITableViewController, Coordinated { switch item.type { case .item: type = "Item" - icon = UIImage(named: item.id)! + icon = UIImage(named: item.id) ?? UIImage.fromAsset(.it) case .quest: type = "Quest" - icon = UIImage(named: "spy")! + icon = UIImage.fromAsset(.spy) } - let cell: ForayTableViewCell = tableView.dequeueReusableCell(withIdentifier: "ForayTableViewCell", for: indexPath) as! ForayTableViewCell + guard let cell = tableView.dequeueReusableCell(withIdentifier: "ForayTableViewCell", for: indexPath) as? ForayTableViewCell else { return ForayTableViewCell() } cell.setData(name: item.name, desc: type + "ID: " + item.id, img: icon) return cell } -- cgit