2016-05-18 3 views
1

私は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回だけ動作しますか?私が忘れてしまったことをやっているリセットがありますか?

ありがとうございました。

+0

FYI - リモートデータアクセスとXML解析がバックグラウンドスレッドで行われるように、実際にコードをリファクタリングする必要があります。 – rmaddy

+0

バックグラウンドネットワークの要求と、各解析に新しいNSXMLParserをインスタンス化することを推奨します。さて、特定の要素の内容が 'foundCharacters'の一回の呼び出しで返されるとは決して考えないでください。 'foundCharacters'内のロジックは全て' didEndElement'に属します。 'didStartElement'は文字列変数を初期化する必要があります。' foundCharacters'はその文字列に追加するだけで、 'didEndElement'はその文字列を解釈してそれを実行するロジックを実行します。 – Rob

+1

コメントありがとうございました。私はそれをバックグラウンドのスレッドに入れ、あなたの提案どおりに私のロジックをdidEndElementに入れます。非常に有益な、私は感謝します! –

答えて

0

NSXMLParserの特定のインスタンスは1回しか使用できないと確信しています。再度解析するたびに新しいインスタンスを作成します。

func parseClanlordInformation() { 
    // reset players list 
    players.removeAll() 
    // Stop the previous parsing operation in case it was still running 
    parser.abortParsing() 

    // Setup new parser 
    let url: String = "http://www.deltatao.com/clanlord/status/cldata.xml" 
    let urlToSend: NSURL = NSURL(string: url)! 

    parser = NSXMLParser(contentsOfURL: urlToSend)! 
    parser.delegate = self 

    // 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() 
} 

これはまた、あなたがviewDidLoadでパーサの設定を削除できることを意味します。

関連する問題