0

I am building XML parser in swift and I faced several problems. First: Xcode sometimes throws new errors such as BAD_ACCESS and sometimes works perfectly. Second: same situation, I sometimes get error on converting pubDate which get as string to NSDate and sometimes it works absolutely perfect. The thing is that I am parsing the data from several links using for loop and in that loop I have dispatch with Utility class. I guess it could be the problem.

Here is the code of my NSXMLParserDelegate:

class Parser: NSObject, NSXMLParserDelegate {

    var title: String!
    var link: String!
    var pubDate: String!
    var currentElement = String()
    var isInItem = false
    var URL: String!
    var lastBuildDate: String!
    var parser: NSXMLParser!
    var delegate: ParserDelegate!
    var currentSource = [String]()
    var all = [Item]()

    var count = 0

    init(currentSource: [String]) {
        self.currentSource = currentSource
    }

    func parse(){
        all.removeAll()
        count = 0
        for url in currentSource {
            dispatch(queue: .Background) {
                self.parser = NSXMLParser(contentsOfURL: NSURL(string: url)!)
                self.parser.delegate = self
                self.parser.parse()
            }
        }
    }

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        if elementName == "item"{
            isInItem = true
            link = ""
            title = ""
            pubDate = ""
        }
        else if elementName == "lastBuildDate"{
            lastBuildDate = String()
        }

        if isInItem{
            switch elementName{
            case "pubDate":
                pubDate = String()
                currentElement = "pubDate"
            case "title":
                title = String()
                currentElement = "title"
            case "link":
                link = String()
                currentElement = "link"
            default:
                break
            }
        }
    }

    func parser(parser: NSXMLParser, foundCharacters string: String) {
        if isInItem{
            switch currentElement {
            case "pubDate":
                pubDate = pubDate + string
            case "title":
                title = title + string
            case "link":
                link = link + string
            default:
                break
            }
        }
        else if currentElement == "lastBuildDate"{
            lastBuildDate = lastBuildDate + string
        }
    }

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if isInItem{
            currentElement = ""
        }

        if elementName == "item" {

            isInItem = false
            let item = Item()
            item.link = link
            item.title = title
            item.timeAgo = Double.time(NSDate().timeIntervalSinceDate(NSDate.getDate(pubDate)))
            item.timeDiff = NSDate().timeIntervalSinceDate(NSDate.getDate(pubDate))
            all.append(item)
        }
    }

    func parserDidEndDocument(parser: NSXMLParser) {
        count += 1
        if count == currentSource.count{
            all.sortInPlace({$0.timeDiff < $1.timeDiff})
            delegate.parseArray(all)
            print(all.count)
        }
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
Robert Kim
  • 133
  • 1
  • 2
  • 8
  • 1
    So if I understand it correctly, you start multiple parallel operations which all modify the same instance properties, without synchronization. Yes, that is a problem. – Martin R Jun 25 '16 at 19:38
  • Thank you for the quick response. Any suggestions how to fix that? Maybe creating news instances of Parser every time? – Robert Kim Jun 25 '16 at 19:50
  • Yep. You're using properties to keep track of where you are in the parsing, so you need a separate set for each concurrent parser. – Rob Jun 25 '16 at 19:51
  • I will try that and write later – Robert Kim Jun 25 '16 at 19:53
  • this still is not working – Robert Kim Jun 26 '16 at 04:51
  • Well, that change was needed anyway, because you definitely don't want concurrent iterations using the same properties. Perhaps you can update question and show us the latest rendition, because it's hard to debug without seeing what the code looks like. You must now have two classes, one `ParseManager` and `Parser`, the former instantiating multiple instances of the latter? – Rob Jun 27 '16 at 18:54

0 Answers0