#json #swift #sorting
#json #swift #сортировка
Вопрос:
Мое приложение пытается показать рейтинг заражения covid (covid19api.com ) страны. У меня есть pickerview для выбора страны и основной информации о covid. Я отсортировал базу данных по количеству заражений. Мой вопрос в том, как получить индексированное значение отсортированного массива для базы стран при выборе pickerview?
Пытался использовать «firstIndex», но выдает следующую ошибку: для ссылки на операторную функцию ‘==’ в ‘StringProtocol’ требуется, чтобы ‘BasicCovidInfoParams’ соответствовал ‘StringProtocol’
Ниже приведен код для проекта:
struct BasicCovidInfo: Decodable {
var Countries: [BasicCovidInfoParams]
}
struct BasicCovidInfoParams: Decodable {
var Country: String?
var NewConfirmed: Int?
var TotalConfirmed: Int?
var NewDeaths: Int?
var TotalDeaths: Int?
var NewRecovered: Int?
var TotalRecovered: Int?
var Date: String?
}
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
//var basiccountrycovidinfo = BasicCovidInfoParams()
var basiccountrycovidinfo = [BasicCovidInfoParams]()
@IBOutlet weak var rankFirstLbl: UILabel!
@IBOutlet weak var rankSecondLbl: UILabel!
@IBOutlet weak var rankThirdLbl: UILabel!
@IBOutlet weak var rankingLbl: UILabel!
@IBOutlet weak var covid19CountryPicker: UIPickerView!
@IBOutlet weak var totalConfirmedLbl: UILabel!
@IBOutlet weak var totalDeathsLbl: UILabel!
@IBOutlet weak var totalRecoverdLbl: UILabel!
@IBOutlet weak var toDateLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
covid19CountryPicker.delegate = self
covid19CountryPicker.dataSource = self
getRemoteCovidJsonFile()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return basiccountrycovidinfo.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.decimal
totalConfirmedLbl.text = numberFormatter.string(from: NSNumber(value: basiccountrycovidinfo[row].TotalConfirmed!))
totalDeathsLbl.text = numberFormatter.string(from: NSNumber(value: basiccountrycovidinfo[row].TotalDeaths!))
totalRecoverdLbl.text = numberFormatter.string(from: NSNumber(value: basiccountrycovidinfo[row].TotalRecovered!))
let dataString = String(basiccountrycovidinfo[row].Date!)
let from = dataString.index(dataString.startIndex, offsetBy:0)
let to = dataString.index(dataString.startIndex, offsetBy:10)
let newString = String(dataString[from..<to])
//print(newString)
toDateLbl.text = "Last Update : " newString
return basiccountrycovidinfo[row].Country
}
func getRemoteCovidJsonFile() {
//Info source = "https://api.covid19api.com/summary"
if let jsonUrlString = URL(string: "https://api.covid19api.com/summary") {
URLSession.shared.dataTask(with: jsonUrlString) { [self] (data, response, error) in
if let data = data {
do {
let decoder = JSONDecoder()
//decoder.keyDecodingStrategy = .convertFromSnakeCase
let covidDataInfo = try decoder.decode(BasicCovidInfo.self, from: data)
//print(covidDataInfo.Countries[1].Country!)
self.basiccountrycovidinfo = covidDataInfo.Countries
let array1 = covidDataInfo.Countries.sorted { (a, b) -> Bool in
return a.TotalConfirmed! > b.TotalConfirmed!
}
let selectedText = pickerView(covid19CountryPicker, titleForRow: 0, forComponent: 0)
if let indexOfSelectedText = array1.firstIndex{$0 == selectedText!} {
print(array1[indexOfSelectedText])
}
DispatchQueue.main.async {
rankFirstLbl.text = array1[0].Country
rankSecondLbl.text = array1[1].Country
rankThirdLbl.text = array1[2].Country
covid19CountryPicker.reloadAllComponents()
}
} catch {
print(error.localizedDescription)
}
}
}.resume()
}
}
}
Комментарии:
1. Ваш код отображается нормально при загрузке ваших данных и предоставляет !несортированный! версия для UIPicker для отображения. Тогда все идет наперекосяк. Прежде чем предоставлять данные UIPicker, вы, похоже, пытаетесь извлечь какой-то выделенный текст, который не даст ничего полезного. Затем вы устанавливаете некоторые метки очень нескоординированным образом из своего отсортированного массива. Я думаю , вы хотите дождаться действия UIPickers и установить свои метки с указанием сведений о выбранной стране, но вы не понимаете, как работает UIPicker. Пожалуйста, ознакомьтесь с его документацией и предоставьте ей отсортированные данные.
Ответ №1:
Вы можете использовать selectedRow
функцию UIPickerView
для получения выбранной строки. Проверьте документацию здесь
func selectedRow(inComponent component: Int) -> Int
Как только вы получите выбранное значение индекса picker, вы можете извлечь значение из массива, используя свойство index.
Комментарии:
1. Большое вам спасибо. Ваше предложение заставило меня изменить подход. Я изменил подход, сначала отсортировав его, прежде чем назначить его pickerview.