I’ve been learning iOS for 5 months with no previous experience in programming language so I’m a newbie. I’m learning how to create a more robust and scalable networking layer in Swift. So far so good i can understand what is going on in here however I’m struggling to refactor my code to accept both POST and GET requests. I have received authorization key for my POST request but I have no idea how to do it. Please give me some guidance
protocol HTTPDataDownloader {
func fetchData <T: Decodable>(as type: T.Type, endpoint: String) async throws -> T
}
extension HTTPDataDownloader {
func fetchData <T: Decodable>(as type: T.Type, endpoint: String) async throws -> T {
guard let url = URL(string: endpoint) else {
throw APIError.requestFailed(description: "Invalid URL")
}
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResponse = response as? HTTPURLResponse else {
throw APIError.requestFailed(description: "Request failed")
}
guard httpResponse.statusCode == 200 else {
throw APIError.invalidStatusCode(statuscode: httpResponse.statusCode)
}
do {
return try JSONDecoder().decode(type, from: data)
} catch {
throw error as? APIError ?? .unknownError(error: error)
}
}
}
class CommentsDataService: HTTPDataDownloader {
private let urlString = "https://jsonplaceholder.typicode.com/posts/1/comments"
func fetchComments() async throws -> [Comments] {
return try await fetchData(as: [Comments].self, endpoint: urlString)
}
}
@Observable
class CommentsViewModel {
var comments = [Comments]()
var errorMessage: String?
private let service: CommentsDataService
init(service: CommentsDataService) {
print("DEBUG: did init")
self.service = service
Task { await fetchComments() }
}
@MainActor
func fetchComments() async {
do {
self.comments = try await service.fetchComments()
} catch {
guard let error = error as? APIError else { return }
self.errorMessage = error.customDescription
}
}
}
struct Comments: Codable, Identifiable {
let id: Int
let name: String
let email: String
let body: String
}
enum APIError: Error {
case invalidData
case jsonParsingFailure
case requestFailed(description: String)
case invalidStatusCode(statuscode: Int)
case unknownError(error: Error)
var customDescription: String {
switch self {
case .invalidData:
return "Invalid data"
case .jsonParsingFailure:
return "Failed to parse JSON"
case .requestFailed(let description):
return "Request failed: (description)"
case .invalidStatusCode(let statuscode):
return "Invalid status code (statuscode)"
case .unknownError(let error):
return "An unknown error occured (error)"
}
}
}
1