-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit eee1a33
Showing
512 changed files
with
28,793 additions
and
0 deletions.
There are no files selected for viewing
190 changes: 190 additions & 0 deletions
190
01-designing-the-data-model/final/OnThisDay.playground/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
// | ||
// OnThisDay.playground | ||
// macOS by Tutorials | ||
// Version 2.0 | ||
// | ||
// by Sarah Reichelt | ||
// | ||
|
||
import Cocoa | ||
|
||
let appState = AppState() | ||
let monthNum = 2 | ||
let dayNum = 29 | ||
|
||
func testData() { | ||
if let day = appState.getDataFor( | ||
month: monthNum, day: dayNum | ||
) { | ||
print(day.displayDate) | ||
print("\(day.deaths.count) deaths") | ||
} else { | ||
print("No data available for that month & day.") | ||
} | ||
} | ||
|
||
extension String { | ||
// String extension to decode HTML entities | ||
var decoded: String { | ||
let attr = try? NSAttributedString( | ||
data: Data(utf8), | ||
options: [ | ||
.documentType: NSAttributedString.DocumentType.html, | ||
.characterEncoding: String.Encoding.utf8.rawValue | ||
], | ||
documentAttributes: nil) | ||
|
||
return attr?.string ?? self | ||
} | ||
} | ||
|
||
enum FetchError: Error { | ||
case badURL | ||
case badResponse | ||
case badJSON | ||
} | ||
|
||
func getDataForDay(month: Int, day: Int) async throws -> Day { | ||
let address = "https://today.zenquotes.io/api/\(month)/\(day)" | ||
guard let url = URL(string: address) else { | ||
throw FetchError.badURL | ||
} | ||
let request = URLRequest(url: url) | ||
|
||
let (data, response) = try await URLSession.shared.data(for: request) | ||
guard | ||
let response = response as? HTTPURLResponse, | ||
response.statusCode < 400 | ||
else { | ||
throw FetchError.badResponse | ||
} | ||
|
||
if let jsonString = String(data: data, encoding: .utf8) { | ||
saveSampleData(json: jsonString) | ||
} | ||
|
||
do { | ||
let day = try JSONDecoder().decode(Day.self, from: data) | ||
return day | ||
} catch { | ||
throw FetchError.badJSON | ||
} | ||
} | ||
|
||
// Task { | ||
// do { | ||
// try await getDataForDay(month: 2, day: 29) | ||
// } catch { | ||
// print(error) | ||
// } | ||
// } | ||
|
||
// if let data = readSampleData() { | ||
// do { | ||
// let day = try JSONDecoder().decode(Day.self, from: data) | ||
// // print(day.displayDate) | ||
// // print(day.births.count) | ||
// // print(day.births[0].links) | ||
// // print(day.births[0].text) | ||
// // print(day.births[0].year) | ||
// | ||
// appState.days[day.displayDate] = day | ||
// testData() | ||
// } catch { | ||
// print(error) | ||
// } | ||
// } | ||
|
||
Task { | ||
do { | ||
let day = try await getDataForDay( | ||
month: monthNum, | ||
day: dayNum | ||
) | ||
appState.days[day.displayDate] = day | ||
testData() | ||
} catch { | ||
print(error) | ||
} | ||
} | ||
|
||
struct Day: Decodable { | ||
let date: String | ||
let data: [String: [Event]] | ||
|
||
var events: [Event] { data[EventType.events.rawValue] ?? [] } | ||
var births: [Event] { data[EventType.births.rawValue] ?? [] } | ||
var deaths: [Event] { data[EventType.deaths.rawValue] ?? [] } | ||
|
||
var displayDate: String { | ||
date.replacingOccurrences(of: "_", with: " ") | ||
} | ||
} | ||
|
||
struct Event: Decodable, Identifiable { | ||
let id = UUID() | ||
let text: String | ||
let year: String | ||
let links: [EventLink] | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case text | ||
case links | ||
} | ||
|
||
init(from decoder: Decoder) throws { | ||
let values = try decoder.container(keyedBy: CodingKeys.self) | ||
|
||
let rawText = try values.decode(String.self, forKey: .text) | ||
let textParts = rawText.components(separatedBy: " – ") | ||
if textParts.count == 2 { | ||
year = textParts[0] | ||
text = textParts[1].decoded | ||
} else { | ||
year = "?" | ||
text = rawText.decoded | ||
} | ||
|
||
let allLinks = try values.decode( | ||
[String: [String: String]].self, | ||
forKey: .links | ||
) | ||
|
||
var processedLinks: [EventLink] = [] | ||
for (_, link) in allLinks { | ||
if | ||
let title = link["2"], | ||
let address = link["1"], | ||
let url = URL(string: address) { | ||
processedLinks.append( | ||
EventLink(id: UUID(), title: title, url: url) | ||
) | ||
} | ||
} | ||
links = processedLinks | ||
} | ||
} | ||
|
||
struct EventLink: Decodable, Identifiable { | ||
let id: UUID | ||
let title: String | ||
let url: URL | ||
} | ||
|
||
enum EventType: String { | ||
case events = "Events" | ||
case births = "Births" | ||
case deaths = "Deaths" | ||
} | ||
|
||
// 1 | ||
class AppState { | ||
// 2 | ||
var days: [String: Day] = [:] | ||
// 3 | ||
func getDataFor(month: Int, day: Int) -> Day? { | ||
let monthName = Calendar.current.monthSymbols[month - 1] | ||
let dateString = "\(monthName) \(day)" | ||
return days[dateString] | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
01-designing-the-data-model/final/OnThisDay.playground/Sources/Files.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// | ||
// Files.swift | ||
// macOS by Tutorials | ||
// Version 2.0 | ||
// | ||
// by Sarah Reichelt | ||
// | ||
|
||
import Foundation | ||
|
||
public var sampleFileURL: URL { | ||
URL.downloadsDirectory.appending(path: "SampleData.json") | ||
} | ||
|
||
public func saveSampleData(json: String) { | ||
do { | ||
try json.write(to: sampleFileURL, atomically: true, encoding: .utf8) | ||
print("Sample JSON data saved to \(sampleFileURL.path)") | ||
} catch { | ||
print(error) | ||
} | ||
} | ||
|
||
public func readSampleData() -> Data? { | ||
do { | ||
let data = try Data(contentsOf: sampleFileURL) | ||
return data | ||
} catch { | ||
print(error) | ||
return nil | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
01-designing-the-data-model/final/OnThisDay.playground/contents.xcplayground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='macos' buildActiveScheme='true' importAppTypes='true'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
7 changes: 7 additions & 0 deletions
7
...the-data-model/final/OnThisDay.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
58 changes: 58 additions & 0 deletions
58
01-designing-the-data-model/starter/OnThisDay.playground/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// OnThisDay.playground | ||
// macOS by Tutorials | ||
// Version 2.0 | ||
// | ||
// by Sarah Reichelt | ||
// | ||
|
||
import Cocoa | ||
|
||
extension String { | ||
// String extension to decode HTML entities | ||
var decoded: String { | ||
let attr = try? NSAttributedString( | ||
data: Data(utf8), | ||
options: [ | ||
.documentType: NSAttributedString.DocumentType.html, | ||
.characterEncoding: String.Encoding.utf8.rawValue | ||
], | ||
documentAttributes: nil) | ||
|
||
return attr?.string ?? self | ||
} | ||
} | ||
|
||
enum FetchError: Error { | ||
case badURL | ||
case badResponse | ||
case badJSON | ||
} | ||
|
||
func getDataForDay(month: Int, day: Int) async throws { | ||
let address = "https://today.zenquotes.io/api/\(month)/\(day)" | ||
guard let url = URL(string: address) else { | ||
throw FetchError.badURL | ||
} | ||
let request = URLRequest(url: url) | ||
|
||
let (data, response) = try await URLSession.shared.data(for: request) | ||
guard | ||
let response = response as? HTTPURLResponse, | ||
response.statusCode < 400 | ||
else { | ||
throw FetchError.badResponse | ||
} | ||
|
||
if let jsonString = String(data: data, encoding: .utf8) { | ||
saveSampleData(json: jsonString) | ||
} | ||
} | ||
|
||
Task { | ||
do { | ||
try await getDataForDay(month: 2, day: 29) | ||
} catch { | ||
print(error) | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
01-designing-the-data-model/starter/OnThisDay.playground/Sources/Files.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// | ||
// Files.swift | ||
// macOS by Tutorials | ||
// Version 2.0 | ||
// | ||
// by Sarah Reichelt | ||
// | ||
|
||
import Foundation | ||
|
||
public var sampleFileURL: URL { | ||
URL.downloadsDirectory.appending(path: "SampleData.json") | ||
} | ||
|
||
public func saveSampleData(json: String) { | ||
do { | ||
try json.write(to: sampleFileURL, atomically: true, encoding: .utf8) | ||
print("Sample JSON data saved to \(sampleFileURL.path)") | ||
} catch { | ||
print(error) | ||
} | ||
} | ||
|
||
public func readSampleData() -> Data? { | ||
do { | ||
let data = try Data(contentsOf: sampleFileURL) | ||
return data | ||
} catch { | ||
print(error) | ||
return nil | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
01-designing-the-data-model/starter/OnThisDay.playground/contents.xcplayground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='macos' buildActiveScheme='true' importAppTypes='true'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
7 changes: 7 additions & 0 deletions
7
...e-data-model/starter/OnThisDay.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.