Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 20 additions & 35 deletions SwiftLeeds/Network/URLSession.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// URLSession.swift
// SwiftLeeds
//
// Created by Matthew Gallagher on 24/09/2023.
//

import Foundation

public extension URLSession {
Expand All @@ -13,49 +6,41 @@ public extension URLSession {
configuration.waitsForConnectivity = true
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 30
configuration.urlCache = nil
configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
configuration.requestCachePolicy = .useProtocolCachePolicy
return URLSession(configuration: configuration)
}()

func cached<Response: Decodable>(_ request: Request<Response>, using decoder: JSONDecoder = .init(),
dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,
fileManager: FileManager = .default, filename: String? = nil) async throws -> Response {
let filename = filename ?? request.url.lastPathComponent
let path = fileManager.temporaryDirectory.appendingPathComponent(filename)

guard let data = fileManager.contents(atPath: path.path.appending(".json")) else { throw NetworkError.cacheNotFound }

let decoded = Task.detached(priority: .userInitiated) {
try Task.checkCancellation()
decoder.dateDecodingStrategy = dateDecodingStrategy
return try decoder.decode(Response.self, from: data)
}

return try await decoded.value
}

func decode<Response: Decodable>(_ request: Request<Response>, using decoder: JSONDecoder = .init(),
dateDecodingStrategy: JSONDecoder.DateDecodingStrategy?,
fileManager: FileManager = .default, filename: String? = nil) async throws -> Response {
let filename = filename ?? request.url.lastPathComponent
let path = fileManager.temporaryDirectory.appendingPathComponent("\(filename).json")

func decode<Response: Decodable>(
_ request: Request<Response>,
using decoder: JSONDecoder = .init(),
dateDecodingStrategy: JSONDecoder.DateDecodingStrategy?,
fileManager: FileManager = .default,
filename: String? = nil
) async throws -> Response {
let decoded = Task.detached(priority: .userInitiated) {
do {
let (data, response) = try await self.data(for: request.urlRequest)

try Task.checkCancellation()

guard let response = response as? HTTPURLResponse else { throw URLError(.badServerResponse) }
guard let response = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}

switch response.statusCode {
case 200...299: break
case 304: throw NetworkError.notModified
default: throw NetworkError.unexpectedStatusCode(response.statusCode)
}

try data.write(to: path, options: .atomicWrite)

let cachedResponse = CachedURLResponse(
response: response,
data: data
)
URLCache.shared.storeCachedResponse(
cachedResponse,
for: request.urlRequest
)

if let eTagKey = request.eTagKey, let eTagValue = response.value(forHTTPHeaderField: "Etag") {
UserDefaults.standard.set(eTagValue, forKey: eTagKey)
Expand Down
6 changes: 1 addition & 5 deletions SwiftLeeds/Views/Local/LocalViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ class LocalViewModel: ObservableObject {
let localResults = try await URLSession.awaitConnectivity.decode(Requests.local, dateDecodingStrategy: Requests.defaultDateDecodingStratergy)
await updateLocal(localResults)
} catch {
if let cachedResponse = try? await URLSession.shared.cached(Requests.local, dateDecodingStrategy: Requests.defaultDateDecodingStratergy) {
await updateLocal(cachedResponse)
} else {
self.error = error
}
self.error = error
}
}

Expand Down
11 changes: 5 additions & 6 deletions SwiftLeeds/Views/My Conference/MyConferenceViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class MyConferenceViewModel: ObservableObject {

func loadSchedule() async throws {
do {
let schedule = try await URLSession.awaitConnectivity.decode(Requests.schedule, dateDecodingStrategy: Requests.defaultDateDecodingStratergy)
let schedule = try await URLSession.awaitConnectivity.decode(
Requests.schedule,
dateDecodingStrategy: Requests.defaultDateDecodingStratergy
)
await updateSchedule(schedule)

do {
Expand All @@ -29,11 +32,7 @@ class MyConferenceViewModel: ObservableObject {
throw(error)
}
} catch {
if let cachedResponse = try? await URLSession.shared.cached(Requests.schedule, dateDecodingStrategy: Requests.defaultDateDecodingStratergy) {
await updateSchedule(cachedResponse)
} else {
throw(error)
}
throw error
}
}

Expand Down
6 changes: 1 addition & 5 deletions SwiftLeeds/Views/Sponsors/SponsorsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ final class SponsorsViewModel: ObservableObject {
let sponsors = try await URLSession.awaitConnectivity.decode(Requests.sponsors, dateDecodingStrategy: Requests.defaultDateDecodingStratergy)
await updateSponsors(sponsors)
} catch {
if let cachedResponse = try? await URLSession.shared.cached(Requests.sponsors, dateDecodingStrategy: Requests.defaultDateDecodingStratergy) {
await updateSponsors(cachedResponse)
} else {
throw(error)
}
throw error
}
}

Expand Down