Swift 中的通用网络层

问题描述 投票:0回答:1

我已经学习 iOS 5 个月了,之前没有任何编程语言经验,所以我是一个新手。我正在学习如何在 Swift 中创建更强大且可扩展的网络层。到目前为止,我可以理解这里发生的事情,但是我正在努力重构我的代码以接受 POST 和 GET 请求。我已收到 POST 请求的授权密钥,但我不知道该怎么做。请给我一些指导

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)"
        }
    }
}
swift
1个回答
0
投票

您选择的方法 -

URLSession.shared.data
不允许您进行太多自定义。因此,您需要使用同一对象的其他众多方法之一。与您使用的最接近的是另一种
data(for:delegate:)
方法,它接受不同的参数 -
URLRequest
,您可以在其中指定方法:

var request = URLRequest(url: url)
request.method = "POST"
© www.soinside.com 2019 - 2024. All rights reserved.