diff options
Diffstat (limited to 'foray')
-rw-r--r-- | foray/ForayItems.swift | 25 | ||||
-rw-r--r-- | foray/ForayNetworkManager.swift | 50 | ||||
-rw-r--r-- | foray/ForayTableViewController.swift | 83 |
3 files changed, 92 insertions, 66 deletions
diff --git a/foray/ForayItems.swift b/foray/ForayItems.swift new file mode 100644 index 0000000..f1a1089 --- /dev/null +++ b/foray/ForayItems.swift @@ -0,0 +1,25 @@ +// +// ForayItems.swift +// foray +// +// Created by Nicholas Tay on 20/3/2022. +// + +import Foundation + +enum ItemType: String, Decodable { + case item + case quest +} + +struct YearSection { + var year: Date + var items: [PenguinItem] +} + +struct PenguinItem: Decodable { + var type: ItemType + var releaseDate: Date + var id: String + var name: String +} diff --git a/foray/ForayNetworkManager.swift b/foray/ForayNetworkManager.swift new file mode 100644 index 0000000..ab1e2b5 --- /dev/null +++ b/foray/ForayNetworkManager.swift @@ -0,0 +1,50 @@ +// +// ForayNetworkManager.swift +// foray +// +// Created by Nicholas Tay on 20/3/2022. +// + +import Foundation + +class ForayNetworkManager { + static let shared = ForayNetworkManager() + + var basicUsername: String? = nil + var basicPassword: String? = nil + + // Reuse JSON decoder, allows for customisation of things like date decode if required + var jsonDecoder: JSONDecoder = { + let jd = JSONDecoder() + // Defaults to year-month-date format + jd.dateDecodingStrategy = .custom({ (decoder) -> Date in + let container = try decoder.singleValueContainer() + let dateStr = try container.decode(String.self) + + let dateFormat = DateFormatter() + dateFormat.dateFormat = "yyyy-MM-dd" + + return dateFormat.date(from: dateStr)! + }) + return jd + }() + + func get<T: Decodable>(url: String, + onComplete: @escaping ([T]) -> ()) { + var request = URLRequest(url: URL(string: url)!) + request.cachePolicy = .reloadRevalidatingCacheData // Needed otherwise default caching policy seems not to check properly + + // Basic auth if required + if (basicUsername != nil && basicPassword != nil) { + let authData = (basicUsername! + ":" + basicPassword!).data(using: .utf8)!.base64EncodedString() + request.addValue("Basic \(authData)", forHTTPHeaderField: "Authorization") + } + + URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in + let items = try! self.jsonDecoder.decode([T].self, from: data!) + + // Possibly passing back to UI, need to do it on the main thread (I think due to async?) + DispatchQueue.main.async { onComplete(items) } + }).resume() + } +} diff --git a/foray/ForayTableViewController.swift b/foray/ForayTableViewController.swift index a7581d2..2732fce 100644 --- a/foray/ForayTableViewController.swift +++ b/foray/ForayTableViewController.swift @@ -7,29 +7,6 @@ import UIKit -enum ItemType: String, Decodable { - case item - case quest -} - -struct PenguinItem: Decodable { - var type: ItemType - var releaseDate: Date - var id: String - var name: String -} - -struct YearSection { - var year: Date - var items: [PenguinItem] -} - -private func parseDate(_ str : String) -> Date { - let dateFormat = DateFormatter() - dateFormat.dateFormat = "yyyy-MM-dd" - return dateFormat.date(from: str)! -} - private func firstDayOfYear(date: Date) -> Date { let calendar = Calendar.current let components = calendar.dateComponents([.year], from: date) @@ -75,50 +52,24 @@ class ForayTableViewController: UITableViewController { } func reloadApiData() { - loadApiData(onComplete: { (apiItems) in - var items = apiItems - items.sort { (lhs, rhs) in lhs.releaseDate < rhs.releaseDate } - - let groups = Dictionary(grouping: apiItems) { (item) in - return firstDayOfYear(date: item.releaseDate) - } - self.sections = groups.map { (key, values) in - return YearSection(year: key, items: values) - } - // Sort the sections from oldest year to newest - self.sections.sort { (lhs, rhs) in lhs.year < rhs.year } - - self.tableView.reloadData() - self.refreshControl?.endRefreshing() - }) - } - - func loadApiData(onComplete: @escaping ([PenguinItem]) -> ()) { - var request = URLRequest(url: URL(string: "https://users.windblume.net/~nick/upload/dummy.json")!) - request.cachePolicy = .reloadRevalidatingCacheData // Needed otherwise default caching policy seems not to check properly - - // Basic auth if required - //let authData = ("ext:PASSWORD").data(using: .utf8)!.base64EncodedString() - //request.addValue("Basic \(authData)", forHTTPHeaderField: "Authorization") - - URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in - print("finished getting data") - print(response!) - - let jsonDecoder = JSONDecoder() - jsonDecoder.dateDecodingStrategy = .custom({ (decoder) -> Date in - let container = try decoder.singleValueContainer() - let dateStr = try container.decode(String.self) - return parseDate(dateStr) + ForayNetworkManager.shared.get( + url: "https://users.windblume.net/~nick/upload/dummy.json", + onComplete: { (apiItems: [PenguinItem]) in + var items = apiItems + items.sort { (lhs, rhs) in lhs.releaseDate < rhs.releaseDate } + + let groups = Dictionary(grouping: apiItems) { (item) in + return firstDayOfYear(date: item.releaseDate) + } + self.sections = groups.map { (key, values) in + return YearSection(year: key, items: values) + } + // Sort the sections from oldest year to newest + self.sections.sort { (lhs, rhs) in lhs.year < rhs.year } + + self.tableView.reloadData() + self.refreshControl?.endRefreshing() }) - let items = try! jsonDecoder.decode([PenguinItem].self, from: data!) - print("json decoded") - - // Passing back to UI, need to do it on the main thread (I think due to async?) - DispatchQueue.main.async { - onComplete(items) - } - }).resume() } // MARK: - Table view data source |