在 Swift 中向用户显示网络错误消息

Posted

技术标签:

【中文标题】在 Swift 中向用户显示网络错误消息【英文标题】:Displaying networking error message to user in Swift 【发布时间】:2020-08-18 11:53:54 【问题描述】:

问题是如何使这段代码可重用,尤其是网络方法中的错误检查和完成处理程序中的条件,所以我没有重复的代码?

我创建了一个方法,该方法使用 URLSession 发出网络请求,并使用状态码作为参数调用完成处理程序。在完成处理中,我创建了一个显示错误消息或基于状态码执行 segue 的条件。所有这些代码都有效,但我想让它可重用,所以我没有重复的代码。

联网方式:

func saveMessage(data: String, day: String, completion: @escaping (Int)->()) 
    let url = URL(string: "\(Constants.baseURL)/daily_mindset/today_message")
    guard let requestUrl = url else  fatalError() 
    var request = URLRequest(url: requestUrl)
    request.httpMethod = "POST"
    
    // Set HTTP Request Header
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let jsonData = encodeJSON(with: data, day: day)
    request.httpBody = jsonData
    
    let task = URLSession.shared.dataTask(with: request)  (data, response, error) in
        if error != nil 
            completion(700)
            return
        
        
        guard let response = response as? HTTPURLResponse else 
            completion(701)
            return
        

        guard (200...299).contains(response.statusCode) else 
            completion(response.statusCode)
            return
        
        
        guard let mime = response.mimeType, mime == "application/json" else 
            completion(702)
            return
        
        
        guard let data = data else 
            completion(703)
            return
        
        
        do 
            let todoItemModel = try JSONDecoder().decode(MessageData.self, from: data)
            Constants.currentMindsetId = todoItemModel._id!
            print("Response data:\n \(todoItemModel)")
         catch let jsonErr
            print(jsonErr)
        
        completion(response.statusCode)
    
    task.resume()

使用完成处理程序调用网络方法:

messageManager.saveMessage(data: textView.text, day: day, completion: (statusCode: Int) -> Void in
                    if (200...299).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.performSegue(withIdentifier: "ToDailyMindsetScreen", sender: sender)
                        
                     else if (400...499).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Please make sure you filled in the all the required fields."
                        
                     else if (500...599).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Sorry, couldn't reach our server."
                        
                     else if (700...).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Sorry, something went wrong. Try again later."
                        
                    
            )

我想重用的网络方法中的代码:

if error != nil 
            completion(700)
            return
        
        
        guard let response = response as? HTTPURLResponse else 
            completion(701)
            return
        

        guard (200...299).contains(response.statusCode) else 
            completion(response.statusCode)
            return
        
        
        guard let mime = response.mimeType, mime == "application/json" else 
            completion(702)
            return
        
        
        guard let data = data else 
            completion(703)
            return
        

我想重用的完成处理程序中的代码:

if (200...299).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.performSegue(withIdentifier: "ToDailyMindsetScreen", sender: sender)
                        
                     else if (400...499).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Please make sure you filled in the all the required fields."
                        
                     else if (500...599).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Sorry, couldn't reach our server."
                        
                     else if (700...).contains(statusCode) 
                        DispatchQueue.main.async 
                            self.errorLabel.text = "Sorry, something went wrong. Try again later."
                        
                    

【问题讨论】:

也许你应该把这个发到codereview.stackexchange.com 【参考方案1】:

如果错误消息是特定于 ViewController 的,您可以从创建一个函数开始,该函数根据状态代码返回消息,如下所示:

private func getErrorMessageFor(statusCode: Int) -> String? 
    if (200...299).contains(statusCode) 
        //If no error message is returned assume that the request was a success
        return nil
     else if (400...499).contains(statusCode) 
        return "Please make sure you filled in the all the required fields."
     else if (500...599).contains(statusCode) 
        return "Sorry, couldn't reach our server."
     else if (700...).contains(statusCode) 
        return "Sorry, something went wrong. Try again later."
     else 
        return "Message for other errors?"
    

您始终可以将此代码移至 ViewController 子类以提供更通用的错误消息,并在以后覆盖它以提供特定 View Controller 的更详细的错误。

class BaseViewController: UIViewController 
    func getErrorMessageFor(statusCode: Int) -> String? 
        //base implementation here
    


class OtherViewController: BaseViewController 
    override func getErrorMessageFor(statusCode: Int) -> String? 
        //create a new error message only for statusCode 404
        if statusCode == 404 
            return "The requested resource was not found on the server. Please contact the support team"
         else 
            return super.getErrorMessageFor(statusCode: statusCode)
        
     

请记住,随着应用程序的增长,您可能希望创建一个 APIClient 来为您处理网络和错误处理。看看https://bustoutsolutions.github.io/siesta/,很人性化

【讨论】:

以上是关于在 Swift 中向用户显示网络错误消息的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中向祖父视图控制器发送消息

如何在 MERN 堆栈中向用户显示错误

这会导致崩溃..?或者我们也可以在 Swift 中向 nil 发送消息..?

如何在飞镖中向用户返回异常消息?

如何在 PHP + MS SQL 应用程序中向用户显示有关维护和夜间作业的消息

Django 1.4 - 在元字段 Model=User 的表单中向用户字段添加自定义错误消息