swiftnsxmlparsernsxmlparserdelegate

Load XML file from main Bundle in Swift 3.0


I have a .GPX file contains routing info of a hiking trip which I want to load into my app. Everything is ok if I load it from remote URL (https://dl.dropboxusercontent.com/u/45741304/appsettings/Phu_si_Lung_05_01_14.gpx) but I can't load this same file from app bundle (already in "Copy bundle resources" and had correct target membership).

Here's my code for loading this file from remote URL:

var xmlParser: XMLParser!


func startParsingFileFromURL(urlString: String) {
    guard let url = URL(string: urlString) else {
        print("Can't load URL: \(urlString)")
        return
    }
    self.xmlParser = XMLParser(contentsOf: url)
    self.xmlParser.delegate = self
    let result = self.xmlParser.parse()
    print("parse from URL result: \(result)")
    if result == false {
        print(xmlParser.parserError?.localizedDescription)
    }

}

and from the main bundle:

func startParsingFile(fileName: String, fileType: String) {
    guard let urlPath = Bundle.main.path(forResource: fileName, ofType: fileType) else {
        print("Can't load file \(fileName).\(fileType)")
        return
    }
    guard let url:URL = URL(string: urlPath) else {
        print("Error on create URL to read file")
        return
    }
    self.xmlParser = XMLParser(contentsOf: url)
    self.xmlParser.delegate = self
    let result = self.xmlParser.parse()
    print("parse from file result: \(result)")
    if result == false {
        print(xmlParser.parserError?.localizedDescription)
    }
}

Error on load from app bundle:

parse from file result: false
Optional("The operation couldn’t be completed. (Cocoa error -1.)")

Solution

  • You are saying:

    guard let urlPath = Bundle.main.path(forResource: fileName, ofType: fileType) else {
        print("Can't load file \(fileName).\(fileType)")
        return
    }
    guard let url:URL = URL(string: urlPath) else {
        print("Error on create URL to read file")
        return
    }
    

    First, it is very silly to turn a string path into a URL. You knew you wanted a URL, so why didn't you start by calling url(forResource:...)?

    Second, if you ever do turn a string path into a URL, you must make a file URL.