我正在使用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/