URLsession .failure 使应用程序崩溃,因为错误为零

问题描述

我有状态代码 500 时,我试图抛出一个错误。当我点击此行完成时(.failure(错误!))我有“致命错误:在解开可选值时意外发现 nil”是它们是我的 URL 会话功能有问题吗?

func PutRoleLedgerTransaction_DebitdistributorBalance(...,completion: @escaping (Result<Data,Error>) -> Void){
     
    let jsonData = role_ledger_object.data(using: .utf8)
    let componentURL = createURLComponents(path: "")
    
    print(componentURL.url!)
    guard let validURL = componentURL.url else {
        print("URL creation Failed...")
        return
    }
    
    var request = URLRequest(url:validURL)

    request.setValue("application/json",forHTTPHeaderField: "Content-Type" )
    request.setValue("application/json",forHTTPHeaderField: "Accept" )
    
    request.httpMethod = "PUT"
    
    request.httpBody = jsonData
    
    URLSession.shared.dataTask(with: request) { (data,response,error) in
        
        if let httpResponse = response as? HTTPURLResponse {
            print("PutRoleLedgerTransaction API status: \(httpResponse.statusCode)")
            let message: String = HTTPURLResponse.localizedString(forStatusCode: httpResponse.statusCode)
            
            print("httpResponse.allHeaderFields \(message)")
            
            if httpResponse.statusCode > 300{
               
                completion(.failure(error!))
                return
            }
        }
        
        guard let validData = data,error == nil else {
            completion(.failure(error!))
            return
        }
      
        do {
            completion(.success(validData))
        } catch let serializationError {
            
            completion(.failure(serializationError))

        }
    }.resume()
}

解决方法

服务器 500 响应不一定等于 URLSession 错误,您不能粗心地打开可选项。

创建自定义错误

enum HTTPResponseError : Error {
    case serverFailed(String)
}

在闭包中先处理URLSession错误,然后响应,如果状态码不是200则返回消息

URLSession.shared.dataTask(with: request) { (data,response,error) in
    if let error = error {  completion(.failure(error)); return }

    if let httpResponse = response as? HTTPURLResponse {
        print("PutRoleLedgerTransaction API status: \(httpResponse.statusCode)")
        let message: String = HTTPURLResponse.localizedString(forStatusCode: httpResponse.statusCode)
        
        print("httpResponse.allHeaderFields \(message)")
        
        if httpResponse.statusCode != 200 {
           
            completion(.failure(HTTPResponseError.serverFailed(message)))
            return
        }
    }
    // The do block makes no sense if no error is being thrown
    // do {
        // force unwrapping data is safe if error is nil.
        completion(.success(data!))
    // } catch {
        
    //    completion(.failure(error))
    // }
    ...