如何避免应用程序从API获取数据时,当数组为空崩溃

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

我检查我的应用程序,我试图登录,并登录自己的帐户顺利突然坠毁,它显示了一个致命错误:超出范围的索引出现在这部分代码

completion(demographicsArray[0], nil)

经检查,在后端数据的倾销过程仍在过程,为什么在我结束数组是空的,没有数据被拔出。我怎样才能使应用程序的崩溃,我怎么能包括警报消息将通知用户他们的战绩仍然在进程?请帮我出了一个星期解决这一点,但我仍然解决不了。代码如下仅供您参考。谢谢。

APIService.swift

 static func getPatientInformation(informationType: PatientInformationType, tokenType: String, token: String, hospitalNumber: String, completion: @escaping getPatientInformationTaskCompletion<Any>) {

        var patientInformationURL: URL!

        switch informationType {
            case .allergies:
                patientInformationURL = URL(string: "\(Endpoint.Patient.allergies)?hn=\(hospitalNumber)")
            case .demographics:
                patientInformationURL = URL(string: "\(Endpoint.Patient.demographics)?hn=\(hospitalNumber)")
            case .diagnosis:
                patientInformationURL = URL(string: "\(Endpoint.Patient.diagnosis)?hn=\(hospitalNumber)")
            case .medications:
                patientInformationURL = URL(string: "\(Endpoint.Patient.medications)?hn=\(hospitalNumber)")
        }

        guard patientInformationURL != nil else {
            completion(nil, .invalidURL)
            return
        }

        let header: HTTPHeaders = [
            "Authorization": "\(tokenType) \(token)",
            "Accept": "application/json"
        ]

        Alamofire.request(patientInformationURL, headers: header).responseJSON(completionHandler: { (response) in
            guard HelperMethods.reachability(responseResult: response.result) else {
                completion(nil, .noNetwork)
                return
            }

            guard let statusCode = response.response?.statusCode else {
                completion(nil, .noStatusCode)
                return
            }

            switch(statusCode) {
            case 200:
                guard let jsonData = response.data else {
                    completion(nil, .invalidJSON)

                    return
                }

                let decoder = JSONDecoder()

                switch (informationType) {
                case .allergies:
                    do {
                        let allergyArray = try decoder.decode([Allergies].self, from: jsonData)
                        completion(allergyArray, nil)
                    }catch {
                        completion(nil, .invalidJSON)
                    }
                case .demographics:
                    do {
                        let demographicsArray = try decoder.decode([Demographics].self, from: jsonData)
                            completion(demographicsArray.first, nil)
                        }catch {
                            completion(nil, .invalidJSON)
                    }

                case .diagnosis:
                    do {
                        let diagnosisArray = try decoder.decode([Diagnosis].self, from: jsonData)
                        completion(diagnosisArray, nil)
                    }catch {
                        completion(nil, .invalidJSON)
                    }
                case .medications:
                    do {
                        let medicationArray = try decoder.decode([Medication].self, from: jsonData)
                        completion(medicationArray, nil)
                    }catch {
                        completion(nil, .invalidJSON)
                    }
                }
            case 401:
                completion(nil, .unauthorizedToken)
            default:
                print("UNCAPTURED STATUS CODE FROM getPatientInformation\nSTATUS CODE: \(statusCode)")
                completion(nil, .uncapturedStatusCode)
            }
        })
    }

PatientProfileViewController.swift

func getPatientInfo() {
    guard let username = KeychainManager.getUsername(),
        let tokenType = KeychainManager.getTokenType(),
        let token = KeychainManager.getToken() else { return }

    SVProgressHUD.setDefaultMaskType(.black)
    SVProgressHUD.show(withStatus: "Retrieving Patient Information")

    APIService.Patients.getPatientInformation(informationType: .demographics,
                                              tokenType: tokenType, token: token,
                                              hospitalNumber: username) { (demographics, error) in

        guard let patientInformation = demographics as? Demographics, error == nil else {
            if let networkError = error {
                switch networkError {
                    case .noNetwork:
                        let popupDialog = PopupDialog(title: "No Network", message: "\(networkError.rawValue)")
                        popupDialog.addButton(DefaultButton(title: "OK", action: nil))
                        self.present(popupDialog, animated: true, completion: nil)
                    default:
                        let popupDialog = PopupDialog(title: "Error", message: "There is something went wrong. Please try again")
                        popupDialog.addButton(DefaultButton(title: "OK", action: nil))
                        self.present(popupDialog, animated: true, completion: nil)
                }
            }

            SVProgressHUD.dismiss()
            return
        }



        self.patientDemographics = patientInformation

        self.welcomeLabel.text = self.patientDemographics.displayName ?? "Welcome"

        self.patientInformationTableView.reloadData()
        SVProgressHUD.dismiss()
    }
}
ios arrays swift
2个回答
0
投票

您可以随时检查数组访问它之前足够的元素。

if demographicsArray.count > 0 {
    completion(demographicsArray[0], nil)
} else {
    // handle empty array completion
}

注意:为什么你的数据库处理之前返回数据?


0
投票

我更喜欢用“后卫”,而不是“如果”

guard demographicsArray.count > 0 else {
  completion(nil, .noDemographicsAtPosition)
}

completion(resonseToSend, nil)

我觉得这种方式更具有可读性。

提醒:getPatientInformation有很多责任的,如果你把它分成其他的功能,如将是巨大的:

func getPatientInformationURL() -> String
func processResponse(completion: @escaping getPatientInformationTaskCompletion<Any>)

可能成为你的代码更易读,希望它可以帮助你。

© www.soinside.com 2019 - 2024. All rights reserved.