我使用的是Google地图SDK。我在更新标记的位置时遇到问题。目前使用xml数据的坐标绘制标记,但是,每次坐标在xml数据中发生变化时,我都会尝试更新它们的位置。这段代码可能有很多不足之处,因为我不太了解,但最终的目标是让这张地图显示我大学校园内公交车的位置,让他们在接收新坐标时在地图上实时移动。谢谢!
import UIKit
import GoogleMaps
class ViewController: UIViewController, GMSMapViewDelegate,
XMLParserDelegate, CLLocationManagerDelegate {
var parser = XMLParser()
var mapsManager = CLLocationManager()
var busArray = [Bus]()
var markerDict: [String: GMSMarker] = [:]
@IBOutlet weak var mapView: GMSMapView!
var refreshTimer = Timer()
struct Pins {
let name: String
let subName: String
let coord: CLLocationCoordinate2D
}
override func viewDidLoad()
{
super.viewDidLoad()
refreshTimer = Timer.scheduledTimer(timeInterval: 2, target: self,
selector: #selector(runRefresh), userInfo: nil, repeats: true)
// Initial Parse:
let urlString = URL(string:
"http://webservices.nextbus.com/service/publicXMLFeed?
a=rutgers&command=vehicleLocations")
self.parser = XMLParser(contentsOf: urlString!)!
self.parser.delegate = self
let success:Bool = self.parser.parse()
if success {
print("success")
getLoc()
} else {
print("parse failure!")
}
mapsManager.delegate = self
mapsManager.desiredAccuracy = kCLLocationAccuracyKilometer
//minimum distance to be moved by device before update
mapsManager.distanceFilter = 1000
// permission to use location service
mapsManager.requestWhenInUseAuthorization()
// permission to use location when the app is run future
mapsManager.requestAlwaysAuthorization()
// Update user location
mapsManager.startUpdatingLocation()
// Make GMSMapView the current view
self.view = mapView
}
// Gets location of pins and maps them to mapView
func getLoc() {
for bus in busArray {
let pins = [
Pins(name: bus.routeTag, subName: "\(bus.busID)",
coord: bus.coordinate)
]
for pin in pins {
let coord = pin.coord
let identifier = pin.subName
self.markerDict[identifier]?.position = coord
let pinMarker = GMSMarker()
pinMarker.position = pin.coord
pinMarker.title = pin.name
pinMarker.snippet = pin.subName
pinMarker.tracksViewChanges = true
pinMarker.map = mapView
markerDict[pin.name] = pinMarker
}
}
}
// PROBLEM HERE: FUNCTION IS SUPPOSED TO UPDATE MARKER POSITIONS WHEN
NEW COORDINATES ARE RECEIVED FROM THE XML PARSING
func updateLoc() {
for bus in busArray {
let pins = [
Pins(name: bus.routeTag, subName: "\(bus.busID)", coord:
bus.coordinate)
]
for pin in pins {
let pinMarker = GMSMarker()
pinMarker.position = pin.coord
pinMarker.title = pin.name
pinMarker.snippet = pin.subName
pinMarker.tracksViewChanges = true
// print(pinMarker)
}
}
}
//MARK: REFRESH FUNCTION WHICH IS CALLED BY TIMER IN VIEW. RECALLS
PARSE, UPDATE LOCATION FUNCTION
@objc func runRefresh() {
let urlString = URL(string:
"http://webservices.nextbus.com/service/publicXMLFeed?
a=rutgers&command=vehicleLocations")
self.parser = XMLParser(contentsOf: urlString!)!
self.parser.delegate = self
let success:Bool = self.parser.parse()
if success {
print("success")
updateLoc()
} else {
print("parse failure!")
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus)
{
if (status == CLAuthorizationStatus.authorizedWhenInUse)
{
mapView?.isMyLocationEnabled = true //to get user’s current location
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let newLocation = locations.last
mapView?.camera = GMSCameraPosition.camera(withTarget: newLocation!.coordinate, zoom: 15.0)
mapView?.settings.myLocationButton = true
self.view = self.mapView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: PARSING FUNCTIONS ->
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
if(elementName=="vehicle")
{
let bus = Bus()
for string in attributeDict {
let strvalue = string.value as NSString
switch string.key {
case "id":
bus.busID = strvalue.integerValue
break
case "routeTag":
bus.routeTag = strvalue as String
break
case "lat":
bus.coordinate.latitude = strvalue.doubleValue
break
case "lon":
bus.coordinate.longitude = strvalue.doubleValue
break
case "speedKmHr":
bus.speed = strvalue.integerValue
break
default:
break
}
}
busArray.append(bus)
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
// for bus in self.busArray {
// print("\(bus.busID)\n\(bus.routeTag)\n\(bus.coordinate)\n\(bus.speed) mph");
// print("\n")
// }
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
// BUS CLASS INITIALIZES OBJECTS TO HOLD VALUES FROM PARSE DATA
class Bus: NSObject {
var busID:Int = 0
var routeTag:String = ""
var coordinate = CLLocationCoordinate2D()
var speed:Int = 0
}