[英]How to avoid app crashing when pulling data from API when array is empty
我正在檢查我的應用程序,嘗試登錄后順利登錄了我的帳戶,然后突然崩潰了,並顯示了致命錯誤:這部分代碼中出現索引超出范圍
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()
}
}
您始終可以在訪問數組之前檢查數組是否包含足夠的元素。
if demographicsArray.count > 0 {
completion(demographicsArray[0], nil)
} else {
// handle empty array completion
}
注意:為什么數據庫在處理數據之前先返回數據?
我更喜歡使用“后衛”而不是“如果”
guard demographicsArray.count > 0 else {
completion(nil, .noDemographicsAtPosition)
}
completion(resonseToSend, nil)
我認為這種方式更具可讀性。
忠告:getPatientInformation承擔很多責任,如果將其划分為其他函數,例如:
func getPatientInformationURL() -> String
func processResponse(completion: @escaping getPatientInformationTaskCompletion<Any>)
可能它使您的代碼更具可讀性,希望對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.