so in my other question I asked, I found out that I can create easily gpx files, but now I need to display the content of the gpx file as a MKPolygon. Before, I had created the list with all the coordinates in a plist file, this was easy to read since I could just make a NSDictionary and read it from there and finding the location using the keys that a plist supplies, however it doesn't seem to work this easy in a gpx file.
I've created this little snipped of code to read the whole content of the gpx file:
if fileManager.fileExistsAtPath(filePath) {
let dataBuffer = NSData(contentsOfFile: filePath)
let dataString = NSString(data: dataBuffer!, encoding: NSUTF8StringEncoding)
print (dataString)
}
So now I have the whole text in a string but I don't need all this:
<?xml version="1.0" encoding="UTF-8"?>
<trk>
<name>test</name>
<desc>Length: 1.339 km (0.832 mi)</desc>
<trkseg>
<trkpt lat="-39.2505337" lon="-71.8418312"></trkpt>
<trkpt lat="-39.2507414" lon="-71.8420136"></trkpt>
</trkseg>
</trk>
</gpx>
I just need the latitudes and longitudes between the <trkpt>
tags so I can convert them into locations and from there convert it into a MKPolygon.
Any help would be greatly appreciated as I haven't found anything in google on how to read gpx files with swift.
Thanks in advance -Jorge
Ok I was able to read the gpx file with the following code:
import Foundation
import MapKit
//NSXMLParserDelegate needed for parsing the gpx files and NSObject is needed by NSXMLParserDelegate
class TrackDrawer: NSObject, NSXMLParserDelegate {
//All filenames will be checked and if found and if it's a gpx file it will generate a polygon
var fileNames: [String]! = [String]()
init(fileNames: [String]) {
self.fileNames = fileNames
}
//Needs to be a global variable due to the parser function which can't return a value
private var boundaries = [CLLocationCoordinate2D]()
//Create a polygon for each string there is in fileNames
func getPolygons() -> [MKPolygon]? {
//The list that will be returned
var polyList: [MKPolygon] = [MKPolygon]()
for fileName in fileNames! {
//Reset the list so it won't have the points from the previous polygon
boundaries = [CLLocationCoordinate2D]()
//Convert the fileName to a computer readable filepath
let filePath = getFilePath(fileName)
if filePath == nil {
print ("File \"\(fileName).gpx\" does not exist in the project. Please make sure you imported the file and dont have any spelling errors")
continue
}
//Setup the parser and initialize it with the filepath's data
let data = NSData(contentsOfFile: filePath!)
let parser = NSXMLParser(data: data!)
parser.delegate = self
//Parse the data, here the file will be read
let success = parser.parse()
//Log an error if the parsing failed
if !success {
print ("Failed to parse the following file: \(fileName).gpx")
}
//Create the polygon with the points generated from the parsing process
polyList.append(MKPolygon(coordinates: &boundaries, count: boundaries.count))
}
return polyList
}
func getFilePath(fileName: String) -> String? {
//Generate a computer readable path
return NSBundle.mainBundle().pathForResource(fileName, ofType: "gpx")
}
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
//Only check for the lines that have a <trkpt> or <wpt> tag. The other lines don't have coordinates and thus don't interest us
if elementName == "trkpt" || elementName == "wpt" {
//Create a World map coordinate from the file
let lat = attributeDict["lat"]!
let lon = attributeDict["lon"]!
boundaries.append(CLLocationCoordinate2DMake(CLLocationDegrees(lat)!, CLLocationDegrees(lon)!))
}
}
}
I hope it helps someone
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With