我正在使用nsxmlparser解析xml。
然而,didstartelement常常没有被调用。
我调查了这个问题,但找不到答案。
这是我的密码。

          //
      //  WorkList.swift
      //  ShotAlertForSwift
      //
      //  Created by xxxxxx on 3/16/15.
      //  Copyright (c) 2015 xxxxxxxx. All rights reserved.
      //

      import UIKit


      class WorkList: UIViewController,UITableViewDataSource,UITableViewDelegate,NSURLSessionTaskDelegate,NSURLSessionDataDelegate,NSXMLParserDelegate{

          @IBOutlet weak var workview: UITableView!

          var appCode:AppCode!
          var workAry:NSMutableArray!
          var param:NSMutableDictionary?
          var start:Int = 0
          var total:Int = 0

          var isLoading = false
          var initLoading = true
          var nowLoading = false
          var notParseFlag = false
          var nowCount:Int = 0
          var currentNodeName:String?
          var currentNodeContent:String?
          var footerIndicator: UIActivityIndicatorView!
          var session:NSURLSession!
          var workdata:NSMutableArray!

          let listmax:Int = 100
          let PageSize = 20


          var xmlUrl : NSURL!
              {
              didSet{

                  println(self.xmlUrl)
                  if (!self.isLoading) {
                      if self.initLoading == true{
                          SVProgressHUD.showWithStatus("読み込み中")
                      }else{
                          self.footerIndicator.startAnimating()
                      }
                      self.nowCount = workdata.count
                      self.isLoading = true

                      let request : NSURLRequest = NSURLRequest(URL:xmlUrl)

                      //タイムアウトは15秒
                      var config = NSURLSessionConfiguration.defaultSessionConfiguration()
                      config.timeoutIntervalForRequest = 10

                      self.session = NSURLSession(configuration: config,
                          delegate: self,
                          delegateQueue: NSOperationQueue.mainQueue())





                      var task:NSURLSessionDataTask = self.session.dataTaskWithRequest(request)
                      task.resume()

                  }

              }
          }
          var xmlUrlStr:String?

          func showAlert(){
              //Cancel 一つだけしか指定できない
              var alert:UIAlertController = UIAlertController(title:"通信エラー",
                  message: "通信に失敗しました。もう一度やり直してください",
                  preferredStyle: UIAlertControllerStyle.Alert)

              let otherAction = UIAlertAction(title: "OK", style: .Default) {
                  action in NSLog("OKOK")
              }
              alert.addAction(otherAction)
              presentViewController(alert, animated: true, completion: nil)

          }



          override func viewDidLoad() {
              super.viewDidLoad()
              workdata = NSMutableArray()
              // Do any additional setup after loading the view, typically from a nib.
              var nib  = UINib(nibName: "WorkItemCell", bundle:nil)
              self.workview.registerNib(nib, forCellReuseIdentifier:"WorkItemCell")
              nib  = UINib(nibName: "NoCountCell", bundle:nil)
              self.workview.registerNib(nib, forCellReuseIdentifier:"NoCountCell")
              footerIndicator = UIActivityIndicatorView()

              appCode = AppCode.init()

              _setParameter()

              //_loadSegment(0, size: 20)
              let paramStr = self.param?.urlEncodedString()
      //println(Const().SHOT_DOMAIN)
              self.xmlUrlStr = Const().SHOT_DOMAIN+Const().WORK_LIST+"?"+paramStr!
              self.xmlUrl = NSURL(string:self.xmlUrlStr!)

          }

          override func viewWillDisappear(animated: Bool) {
              SVProgressHUD.dismiss()
              self.footerIndicator.stopAnimating()
              self.notParseFlag = true
              self.cancelConnect()


          }

          func _setParameter(){
              self.param = NSMutableDictionary()
              if appCode.codeArea != nil && appCode.codeArea != ""{
                  self.param?.setValue(appCode.codeArea, forKey: "a")
              }
              if appCode.codePref != nil && appCode.codePref != ""{
                  self.param?.setValue(appCode.codePref, forKey: "prefcode")
              }
              if appCode.codeStartday != nil && appCode.codeStartday != ""{
                  self.param?.setValue(appCode.codeStartday, forKey: "wdf")
              }
              if appCode.codeMinimumday != nil && appCode.codeMinimumday != ""{
                  self.param?.setValue(appCode.codeMinimumday, forKey: "md")
              }
              if appCode.codeMainjob != nil && appCode.codeMainjob != ""{
                  self.param?.setValue(appCode.codeMainjob, forKey: "mj")
              }
              if appCode.codeTag != nil && appCode.codeTag != ""{
                  self.param?.setValue(appCode.codeTag, forKey: "tags")
              }
              self.param?.setValue(String(start+1), forKey: "start")
              self.param?.setValue(String(PageSize), forKey: "results")
              self.param?.setValue("xml", forKey: "output")
              self.param?.setValue(String(1), forKey: "apliflag")
              self.param?.setValue("key_001", forKey: "key_api")

      //        println(appCode.codePref)
      //        println(self.param)
          }


          /*
          Cellが選択された際に呼び出される.
          */
          func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

              let workdic: AnyObject = workdata[indexPath.row]
              let workid = workdic.objectForKey("WorkId") as String

              let detailUrl = Const().SHOT_DOMAIN+Const().WORK_DETAIL+"/"+workid

              let web:Web! = self.storyboard?.instantiateViewControllerWithIdentifier("web") as Web
              web.url = detailUrl

              self.navigationController?.pushViewController(web, animated: true)



          }


          func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
              return 1
          }

          func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
              if total == 0{
                  return self.view.frame.size.height
              }

              return 185
          }



          func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

              if total == 0{
                  return 1
              }
      //println("============================================")
      //println(total)
      //println(self.workdata.count)
      //println("============================================")
              return self.workdata.count

          }



          /*
          Cellに値を設定する.
          */
          func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

              // Cellの.を取得する.

              if total > 0{
                  let wcell: WorkItemCell = tableView.dequeueReusableCellWithIdentifier("WorkItemCell", forIndexPath: indexPath) as WorkItemCell

                  let workdic: AnyObject = workdata[indexPath.row]

                  let minimumday = workdic.objectForKey("MinimumWorkDay") as String

                  let catchcopy = workdic.objectForKey("CatchCopy") as String
                  let payment = workdic.objectForKey("Payment") as String
                  let paymentunitname = workdic.objectForKey("PaymentUnitName") as String
                  var stationname = workdic.objectForKey("StationName") as? String
                  let applyenddate = workdic.objectForKey("ApplyEndDate") as String
                  let applyenddatediff = workdic.objectForKey("ApplyEndDateDiff") as String
                  var mainjobcodename = workdic.objectForKey("MainJobCodeName") as? String
                  let optiontags = workdic.objectForKey("OptionTags") as? String
                  let tags = workdic.objectForKey("Tags") as? String
                  let workstartdate = workdic.objectForKey("WorkStartDate") as String


                  wcell.minimumdayLabel.text = minimumday+"日"
                  wcell.catchcopyLabel.text = catchcopy
                  if stationname == nil{
                      stationname = ""
                  }
                  wcell.stationLabel.text = "最寄り駅:"+stationname!
                  wcell.paymentunitnameLabel.text = paymentunitname
                  wcell.paymentLabel.text = payment+"円"

                  let diff = applyenddatediff.toInt()
                  wcell.limittitleLabel.text = "応募締切"
                  if diff < 1{
                      wcell.limitLabel.textColor = UIColor.redColor()
                      let limitStr = "残り"+applyenddatediff+"時間"
                      wcell.limitLabel.text = limitStr
                  }else if diff >= 1 && diff < 24 {
                      wcell.limitLabel.textColor = UIColor.blackColor()
                      let limitStr = "残り"+applyenddatediff+"時間"
                      wcell.limitLabel.text = limitStr
                  }else{
                      wcell.limitLabel.textColor = UIColor.blackColor()

                      let limitStr = applyenddate
                      wcell.limitLabel.text = limitStr

                  }


                  if mainjobcodename == nil{
                      mainjobcodename = ""
                  }

                  //タグの処理
                  var tagAry:NSMutableArray?
                  if tags != nil {
                      tagAry?.addObject(tags!)
                  }
                  if optiontags != nil {
                      tagAry?.addObject(optiontags!)
                  }
                  var viewTag:String! = ""
                  if(tagAry?.count > 0){
                      //println("---------------")
                      viewTag = tagAry!.componentsJoinedByString(",")
                  }


                  wcell.mainjobLabel.text = "職種:"+mainjobcodename!
                  wcell.optiontagLabel.text = "こだわり条件:"+viewTag

                  wcell.workstartdateLabel.text = "勤務開始日:"+workstartdate

                  return wcell
              }else{

                  let nocell: NoCountCell = tableView.dequeueReusableCellWithIdentifier("NoCountCell", forIndexPath: indexPath) as NoCountCell
                  nocell.conditionButton.addTarget(self, action: "onClickBack:", forControlEvents: .TouchUpInside)

                  //初期が終わったらfalse
                  if self.initLoading{
                      nocell.conditionButton.hidden = true
                      nocell.messageLabel.hidden = true
                  }else{
                      nocell.conditionButton.hidden = false
                      nocell.messageLabel.hidden = false
                  }

                  return nocell
              }

          }

          func scrollViewDidScroll(scrollView: UIScrollView!) {
              var offset = scrollView.contentOffset.y
              var maxOffset = scrollView.contentSize.height - scrollView.frame.size.height


              //nowLoadgingをtrueにするのは、2重にロードを防ぐため
              //0件時には処理しない
              //20であまりがある場合、もう無いので、処理しない(かつ、totalに達してない)
              //100件以上もロードしない
              //println(self.workdata.count)
              if (maxOffset - offset) <= 40
                  && workdata.count > 0
                  && !self.nowLoading
                  && ((self.workdata.count)%20 == 0 && self.workdata.count < total && self.workdata.count < self.listmax){

                  self.nowLoading = true
                  self.start = self.workdata.count
                  _setParameter()

                  let paramStr = self.param?.urlEncodedString()

                  self.xmlUrlStr = Const().SHOT_DOMAIN+Const().WORK_LIST+"?"+paramStr!
                  self.xmlUrl = NSURL(string:self.xmlUrlStr!)
              }

          }



          func onClickBack(sender: UIButton){

              self.navigationController?.popViewControllerAnimated(true)
          }


          // NSXMLParserDelegate

          var parseKey : String? = nil
          var tmpEntry : NSMutableDictionary! = nil

          let resultKey = "Result"
          let resultSetKey = "ResultSet"
          let urlKey   = "url"

          func parserDidStartDocument(parser: NSXMLParser!)
          {
              println("parse start")
              println(parser)

          }


          func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!){

              parseKey = elementName

              if elementName == resultKey {
                  tmpEntry = NSMutableDictionary()

              } else if elementName == resultSetKey {
                  let attr = attributeDict as NSDictionary

                  let totalStr = attr.objectForKey("totalResultsAvailable") as String
                  let totalreturnstr = attr.objectForKey("totalResultsReturned") as String

                  total = totalStr.toInt()!
              }
          }

          func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!)
          {

              if elementName == resultKey {

                  self.workdata.addObject(tmpEntry)


              }else if parseKey != nil{
                  if (elementName == parseKey && tmpEntry != nil){
                      tmpEntry.setValue(currentNodeContent, forKey: parseKey!)
                  }
              }
              parseKey = nil
              currentNodeContent = nil
          }

          func parser(parser: NSXMLParser!, foundCharacters string: String!)
          {
              currentNodeContent = string
          }

          func parserDidEndDocument(parser: NSXMLParser!)
          {
              if self.initLoading{
                  SVProgressHUD.dismiss()
              }else{
                  self.footerIndicator.stopAnimating()
              }
              self.isLoading = false
              self.initLoading = false
              self.nowLoading = false

              var footer = UIView()
              //footer.backgroundColor = UIColor.clearColor()
              // インジケータを作成する.
              footerIndicator.color = UIColor.blackColor()

              //self.footerIndicator.hidesWhenStopped = true
              footerIndicator.frame.origin.x = self.view.frame.size.width / 2
              footer.addSubview(footerIndicator)

              //ナビゲーションのタイトルに件数をセット
              self.navigationItem.title = "検索結果:"+String(total)+"件"

              //20で割ってもない場合は表示しない
              if self.workdata.count%20 == 0 && self.workdata.count < total && self.workdata.count < self.listmax{
                  self.workview.tableFooterView = footer
              }
              self.workview.reloadData()
          }




          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
              // Dispose of any resources that can be recreated.
              println("didReceiveMemoryWarning")
          }


      }


      extension  WorkList {
          func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void){
              println("request_start")

              if response.isKindOfClass(NSHTTPURLResponse){
                  let httpURLResponse:NSHTTPURLResponse = response as NSHTTPURLResponse

                  let statuscode = httpURLResponse.statusCode
                  println(statuscode)

                  if statuscode == 200{
                      println("success")

                      let disposition:NSURLSessionResponseDisposition = NSURLSessionResponseDisposition.Allow
                      completionHandler(disposition)
                  }else{
                      handleError()
                  }
              }


          }
          func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didBecomeDownloadTask downloadTask: NSURLSessionDownloadTask){
              println("didBecomeDownloadTask")
          }

          func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData){
              if !notParseFlag{
                  println(NSString(data: data, encoding: NSUTF8StringEncoding))
                  var parser : NSXMLParser? = NSXMLParser(data: data)

                  if parser != nil {
                      println("parser ok")
                      // NSXMLParserDelegateをセット
                      parser!.delegate = self;
                      parser!.parse()

                  } else {
                      // パースに失敗した時
                      println("failed to parse XML")
                  }
              }
          }

          func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){
              println(error)
              if error != nil{
                  //println("didCompleteWithError")
                  handleError()
              }


          }
          func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?){
              println(error)

              if error != nil{
                  //println("didBecomeInvalidWithError")
                  handleError()
              }
          }

          func cancelConnect(){
              self.session.getTasksWithCompletionHandler
              {
                  (dataTasks, uploadTasks, downloadTasks) -> Void in

                  self.cancelTasksByUrl(dataTasks     as [NSURLSessionTask])

              }
          }

          func handleError(){
              if self.initLoading{
                  SVProgressHUD.dismiss()
              }else{
                  self.footerIndicator.stopAnimating()
              }
              self.isLoading = false
              self.initLoading = false
              self.nowLoading = false

              //アラートを表示して終了
              showAlert()

              self.workview.reloadData()
          }

          private func cancelTasksByUrl(tasks: [NSURLSessionTask])
          {
              for task in tasks
              {
                  task.cancel()
              }
          }
      }

      extension NSDictionary{
          func urlEncodedString() -> String {

              var parts:NSMutableArray = NSMutableArray()
              for key in self.allKeys {

                  let sKey = key as String
                  let value:String = self.objectForKey(key) as String
                  let eValue = value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
                  var part:String! = (sKey+"="+eValue) as String!
                  parts.addObject(part)
              }
              return parts.componentsJoinedByString("&")
          }
      }

我不明白为什么StartElement有时不被呼叫。
这是什么问题?

最佳答案

我得下决心。
我向nsmutabledata添加了nsdata对象。
这是密码。

var data : NSMutableData? = nil
public func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData){



    self.data!.appendData(data)
    ....you can write your code.



}

关于ios - didstartelement ofiten没有被 swift 调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29432513/

10-12 14:39