私はXMLフィードを読み込んでtableViewにデータを読み込みますが、NSXMLParserを使用してXMLを解析しています。私が最初にデータを解析すると、すべてうまく動作し、私は期待したようにテーブルを作成します。私は定期的にサーバーからのデータを更新するタイマーを設定します。タイマーがトリガされたとき、同じメソッドを使用して別の時間に同じXMLフィードを解析した後、常に失敗します.parser.parse()はfalseを返しますが、エラーは報告されません。私は失敗した行番号と列を取得することができますが、データはXMLを解析したときとはまったく変わりません(そして、その時に働きました)。NSXMLParser parse()は一度だけ動作します
私は私のTableViewControllerでパーサを宣言:のviewDidLoadで
var parser = NSXMLParser()
私はそれを設定します。ViewWillAppearで
let url: String = "http://www.deltatao.com/clanlord/status/cldata.xml"
let urlToSend: NSURL = NSURL(string: url)!
parser = NSXMLParser(contentsOfURL: urlToSend)!
parser.delegate = self
私はそれを呼び出すと、タイマーを設定します。
parseClanlordInformation()
// this will remove the previous timer
timer?.invalidate()
// now start a timer to regularly update the data from the server
startTimer()
そして、parse()を呼び出す関数は次のとおりです。
func parseClanlordInformation() {
// reset players list
players.removeAll()
// Stop the previous parsing operation in case it was still running
parser.abortParsing()
// rebuild the list from scratch
let success: Bool = parser.parse()
if !success {
let error = parser.parserError
let line = parser.lineNumber
let col = parser.columnNumber
print("XML parsing failed at \(line):\(col): \(error?.localizedDescription)")
print(players.count)
}
if parser.parserError != nil {
print("Error: parse failure!")
print(parser.parserError)
}
myTableView.reloadData()
}
とタイマ同じ関数を呼び出します:
func startTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(updateInterval, target: self, selector: #selector(TableViewController.parseClanlordInformation), userInfo: nil, repeats: true)
}
をし、XMLパーサの代表者は、このように設定されています。私は、テーブルがでいっぱいにアプリケーションを実行すると
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName=="exile" || elementName=="race" || elementName=="name" || elementName=="sex" || elementName=="profession" || elementName=="clan" {
if elementName == "exile" {
foundNewPlayer = true
currentPlayer.reset()
}
passData = true
}
}
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName=="exile" || elementName=="race" || elementName=="name" || elementName=="cost" || elementName=="description" {
if elementName == "exile" {
foundNewPlayer=false
players.append(currentPlayer)
}
passData=false
}
}
func parser(parser: NSXMLParser, foundCharacters string: String) {
if foundNewPlayer {
switch currentElement {
case "name":
currentPlayer.name = string
case "race":
var race: String
if string == "of the People" {
race = "Fen'neko"
} else {
race = String(string.characters.dropFirst(2))
}
currentPlayer.race = race
case "sex":
currentPlayer.genre = string
case "profession":
let prof = String(string.characters.dropFirst(2))
currentPlayer.profession = prof
case "clan":
currentPlayer.clan = string
default: break
}
}
}
func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
print(parseError.description)
NSLog("failure error: %@", parseError)
}
最初の更新がトリガーしたときparser.parse()は80行目、1列目またはそれ以降にfalseを返します。
なぜ1回だけ動作しますか?私が忘れてしまったことをやっているリセットがありますか?
ありがとうございました。
FYI - リモートデータアクセスとXML解析がバックグラウンドスレッドで行われるように、実際にコードをリファクタリングする必要があります。 – rmaddy
バックグラウンドネットワークの要求と、各解析に新しいNSXMLParserをインスタンス化することを推奨します。さて、特定の要素の内容が 'foundCharacters'の一回の呼び出しで返されるとは決して考えないでください。 'foundCharacters'内のロジックは全て' didEndElement'に属します。 'didStartElement'は文字列変数を初期化する必要があります。' foundCharacters'はその文字列に追加するだけで、 'didEndElement'はその文字列を解釈してそれを実行するロジックを実行します。 – Rob
コメントありがとうございました。私はそれをバックグラウンドのスレッドに入れ、あなたの提案どおりに私のロジックをdidEndElementに入れます。非常に有益な、私は感謝します! –