SwiftUI - 结合和 Alamofire 解析错误响应

Posted

技术标签:

【中文标题】SwiftUI - 结合和 Alamofire 解析错误响应【英文标题】:SwiftUI - Combine and Alamofire parse error Response 【发布时间】:2021-02-18 19:04:56 【问题描述】:

我的 api .post 方法有这个通用实现:

func post<T: Decodable>(endpoint: Endpoint, parameters: Parameters, responseType: T.Type) -> AnyPublisher<T, Error> 
    sessionManager.request(self.baseUrl + endpoint.path, method: .post, parameters: parameters)
        .publishDecodable(type: responseType)
        .value()
        .mapError(ServiceError.init(error: ))
        .eraseToAnyPublisher()

它正在工作,我认为这就是它在 SwiftUI/Combine 中应该有的样子。我的问题是,当我得到其他状态码然后是 2xx 时,我希望能够解析响应。我找到了this answer 和this article 来了解如何做到这一点。

在这个帮助下,我能够将我的代码更改为:

func post<T: Decodable>(endpoint: Endpoint, parameters: Parameters, responseType: T.Type, completionHandler: @escaping (Result<T, ErrorResponse>) -> Void) 
    sessionManager.upload(multipartFormData: multipartFormData, to: self.baseUrl + endpoint.path, method: .post, headers: headers)
        .validate(statusCode: 200..<300)
        .responseTwoDecodable(of: responseType, completionHandler: completionHandler)

更多信息在这里是我的TwoDecodableResponseSerializer(在这两个链接的帮助下创建):

final class TwoDecodableResponseSerializer<T: Decodable>: ResponseSerializer 
     
    lazy var decoder: JSONDecoder = 
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        return decoder
    ()
    
    private lazy var successSerializer = DecodableResponseSerializer<T>(decoder: decoder)
    private lazy var errorSerializer = DecodableResponseSerializer<ErrorResponse>(decoder: decoder)
    
    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Result<T, ErrorResponse> 
        
        guard let response = response else  return .failure(ErrorResponse()) 
        
        do 
            if response.statusCode < 200 || response.statusCode >= 300 
                let result = try errorSerializer.serialize(request: request, response: response, data: data, error: nil)
                return .failure(result)
             else 
                let result = try successSerializer.serialize(request: request, response: response, data: data, error: nil)
                return .success(result)
            
         catch(let err) 
            return .failure(ErrorResponse())
        
        
    


extension DataRequest 
    @discardableResult func responseTwoDecodable<T: Decodable>(queue: DispatchQueue = DispatchQueue.global(qos: .userInitiated), of t: T.Type, completionHandler: @escaping (Result<T, ErrorResponse>) -> Void) -> Self 
        return response(queue: .main, responseSerializer: TwoDecodableResponseSerializer<T>())  response in
            switch response.result 
            case .success(let result):
                completionHandler(result)
            case .failure(let error):
                completionHandler(.failure(ErrorResponse()))
            
        
    

和错误响应:

class ErrorResponse: Error, Decodable 
    
    var error: Int = 0
    
    enum CodingKeys: String, CodingKey 
        case error = "error"
    
    

它正在工作。这很好,但我想要更多的反应/组合代码。没有关闭。是否可以?你会怎么做呢?

感谢您的帮助

【问题讨论】:

【参考方案1】:

如果您使用自己的ResponseSerializer,您可以使用publishResponse(using:on:) 方法将其与Combine 一起使用。

【讨论】:

这就是我一直在寻找但不知道它存在的东西。谢谢

以上是关于SwiftUI - 结合和 Alamofire 解析错误响应的主要内容,如果未能解决你的问题,请参考以下文章

Swift UI 和 Alamofire 图片上传

值:(failure(Alamofire.AFError.explicitlyCancelled)) 使用 Alamofire 发布者时

Swift之深入解析如何结合Core Data和SwiftUI

在 SwiftUI 视图中结合 onChange 和 onAppear 事件?

swiftui 对成员“navigationBarTitle”的模糊引用

使用 Alamofire 4 (Swift 3) 下载文件的路径