#ios #swift #xcode #uitableview #uipickerview
#iOS #swift #xcode #uitableview #uipickerview
Вопрос:
Я пытаюсь создать приложение для iOS, которое отображает pickerView и TableView. pickerView содержит 50 штатов США, а TableView должен отображать текущие предупреждения о погоде для выбранного штата на основе XML, предоставляемого Национальной метеорологической службой. URL-адрес XML https://alerts.weather.gov/cap/fl.php?x=0 для Флориды, https://alerts.weather.gov/cap/ca.php?x=0 для Калифорнии и так далее. Другими словами, URL-адрес для XML каждого состояния варьируется в зависимости от двухбуквенной аббревиатуры состояния.
До сих пор я заставлял приложение корректно отображать все 50 состояний в pickerView, и когда выбрано каждое состояние, предупреждения о погоде для этого состояния действительно отображаются в TableView. Однако, как только TableView был заполнен предупреждениями о погоде, они никогда не исчезают после этого. Я хочу, чтобы в TableView отображались только предупреждения для состояния, выбранного в данный момент в pickerView. На данный момент предупреждения о погоде для каждого состояния просто продолжают добавляться в TableView друг над другом. Кроме того, если я вернусь к состоянию, которое я выбрал ранее, предупреждения о погоде снова будут добавлены в конец TableView в виде дубликатов. Я не уверен, как правильно заполнить TableView, чтобы он отображал только предупреждения для каждого отдельного состояния одновременно. Кто-нибудь может мне помочь?
Вот мой код:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDataSource, UITableViewDelegate, XMLParserDelegate {
@IBOutlet var statePicker: UIPickerView!
@IBOutlet var alertsTable: UITableView!
var titleFound:Bool = false
var descFound:Bool = false
var alerts:[String] = []
var exps:[String] = []
var abbv:String = ""
var parser = XMLParser()
var states = ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"]
var abbvsList = ["al", "ak", "az", "ar", "ca", "co", "ct", "de", "fl", "ga", "hi", "id", "il", "in", "io", "ks", "ky", "la", "me", "md", "ma", "mi", "mn", "ms", "mo", "mt", "ne", "nv", "nh", "nj", "nm", "ny", "nc", "nd", "oh", "ok", "or", "pa", "ri", "sc", "sd", "tn", "tx", "ut", "vt", "va", "wa", "wv", "wi", "wy"]
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int)->Int
{
return states.count
}
func pickerView(_ pickerView:UIPickerView, titleForRow row: Int, forComponent component: Int)->String?
{
return states[row]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView:UIPickerView, didSelectRow row:Int, inComponent component:Int)
{
var currentState = abbvsList[statePicker.selectedRow(inComponent: 0)]
parser = XMLParser(contentsOf:(NSURL(string:"http://alerts.weather.gov/cap/(currentState).php?x=0") as! URL))!
parser.delegate = self
parser.parse()
alertsTable.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
statePicker.delegate = self
statePicker.dataSource = self
self.alertsTable.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
alertsTable.delegate = self
alertsTable.dataSource = self
}
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
if(elementName == "cap:event") {
titleFound = true
}
if(elementName == "cap:expires") {
descFound = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if(elementName == "cap:event") {
titleFound = false
}
if(elementName == "cap:expires") {
descFound = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if(titleFound) {
alerts.append(string)
}
if(descFound) {
exps.append(string)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return alerts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style:UITableViewCellStyle.subtitle, reuseIdentifier: "cell")
cell.textLabel!.text = alerts[indexPath.row]
cell.detailTextLabel!.text = "Expires: " exps[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//What happens when the cell is tapped`
}
}
Ответ №1:
Вы постоянно добавляете alerts
exps
и никогда не инициализируете их повторно.
In pickerView(_:didSelectRow:inComponent)
, установите alerts
и exps
верните значение empty перед анализом нового ввода:
func pickerView(_ pickerView:UIPickerView, didSelectRow row:Int, inComponent component:Int)
{
var currentState = abbvsList[statePicker.selectedRow(inComponent: 0)]
parser = XMLParser(contentsOf:(NSURL(string:"http://alerts.weather.gov/cap/(currentState).php?x=0") as! URL))!
alerts = []
exps = []
parser.delegate = self
parser.parse()
alertsTable.reloadData()
}
Комментарии:
1. Ах, я знал, что это должно быть что-то вроде этого. Я так долго смотрел на код, что он просто начал размываться -_- Большое вам спасибо!
Ответ №2:
Из кода похоже, что вы добавляете результат веб-запроса в конец alerts
amp; exps
arrays через alerts.append(string)
, exps.append(string)
.
Вместо append
-ing вам нужно сначала очистить массив, а затем добавить результат.