Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.6k views
in Technique[技术] by (71.8m points)

swift - URLsession .failure crash the app because error is nil

I am trying to throw an error when I have status code 500. when I hit this line completion(.failure(error!)) I have "Fatal error: Unexpectedly found nil while unwrapping an Optional value" is they are a problem with my URL session functional?

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()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

A server 500 response is necessarily not equal to an URLSession error, you must not unwrap the optional carelessly.

Create a custom error

enum HTTPResponseError : Error {
    case serverFailed(String)
}

In the closure first handle the URLSession error, then the response and return the message if the status code is not 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))
    // }
    ...

    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...