So I have multiple locations stored in my database, using Geofire. I want to centre the map on a specific one.
I want to know if it is possible to access the firebase database to only retrieve the coordinates saved by GeoFire as a variable so that I can create a CLLocation and centre the map on this one location. Here is my code.
I call getJobLocation in my viewDidLoad. This is where I want to grab the job coordinates from Firebase and then call the other methods i.e. showJobsOnMap using these coordinates
func getJobLocation(jobID: String) {
...
}
func centreMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 2000, 2000)
mapView.setRegion(coordinateRegion, animated: true)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annoIdentifier = "job"
var annotationView: MKAnnotationView?
if annotation.isKind(of: MKUserLocation.self) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "User")
annotationView?.image = UIImage(named:"currentLocationPin")
} else if let deqAnno = mapView.dequeueReusableAnnotationView(withIdentifier: "job") {
annotationView = deqAnno
annotationView?.annotation = annotation
} else {
let MKAV = MKAnnotationView(annotation: annotation, reuseIdentifier: annoIdentifier)
MKAV.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView = MKAV
}
if let annotationView = annotationView, let _ = annotation as? JobAnnotation {
let postsRef = self.dataBaseRef.child("jobs")
postsRef.observe(.value, with: { (posts) in
for _ in posts.children {
annotationView.canShowCallout = true
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.image = UIImage(named: "jobPin")
}
})
}
return annotationView
}
func showJobsOnMap(location: CLLocation) {
let circleQuery = geoFire!.query(at: location, withRadius: 2.5)
_ = circleQuery?.observe(GFEventType.keyEntered, with: { (key, location) in
if let key = key, let location = location {
if key == self.job.postID {
let postsRef = self.dataBaseRef.child("jobs").child(key)
postsRef.observe(.value, with: { (posts) in
for _ in posts.children {
let post = Post(snapshot: posts )
let jobDate = post.postDateTime
let price = post.price
let anno = JobAnnotation(coordinate: location.coordinate, jobID: key, jobDate: jobDate, title: "£\(price) - \(jobDate)")
self.mapView.addAnnotation(anno)
}
})
}
}
})
}
Related
I'm trying to present a view controller with an object within annotation didSelect function. But it's returning nil when I try to print the post.id within the newly presented viewcontroller. If I print post.id within the addAnnotation function it returns fine.
func addAnnotations(post: Post, title: String?, locationName: String?, coords: [CLLocation]) {
for coord in coords {
let CLLCoordType = CLLocationCoordinate2D(latitude: coord.coordinate.latitude,
longitude: coord.coordinate.longitude);
let anno = MKPointAnnotation()
anno.coordinate = CLLCoordType
if title == "" {
anno.title = locationName
} else {
anno.title = title
}
mapView.addAnnotation(anno)
}
}
let activityPreview = ActivityPreviewLauncher()
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
//Returns an error
guard let post = view.annotation?.post else { return }
activityPreview.showActivityPreview()
activityPreview.homeController = self
activityPreview.post = post
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation{
return nil
} else{
let pinIdent = "Pin"
var pinView: MKPinAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: pinIdent) as? MKPinAnnotationView {
dequeuedView.annotation = annotation
pinView = dequeuedView
} else {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: pinIdent)
}
return pinView
}
}
Value of type 'MKAnnotation' has no member 'post'. You have to subclass MKPointAnnotation
class MyAnno: MKPointAnnotation {
var post: Post? = nil
}
in func addAnnotations override your code to
let CLLCoordType = CLLocationCoordinate2D(latitude: coord.coordinate.latitude,
longitude: coord.coordinate.longitude);
let anno = MyAnno()
anno.coordinate = CLLCoordType
anno.post = post
if title == "" {
anno.title = locationName
} else {
anno.title = title
}
mapView.addAnnotation(anno)
then in didSelect check type of your annotation
guard
let anno = view.annotation as? MyAnno,
let post = anno.post
else { return }
smth like this
i have 3 annotation and i draw polyline between first and second annotation but i need the therd one move over that polyline but it's always move in street polyline to the destnation
-my code
func moveDelivery(_ destinationCoordinate : CLLocationCoordinate2D{
self.deliveryAnnotation.coordinate = CLLocationCoordinate2DMake(29.959640, 31.270421)
let sourcePlaceMark = MKPlacemark(coordinate: self.userAnnotation.coordinate)
//sourcePlaceMark.title
let destPlaceMkark = MKPlacemark(coordinate: self.deliveryAnnotation.coordinate)
let sourceItem = MKMapItem(placemark: sourcePlaceMark)
let destItem = MKMapItem(placemark: destPlaceMkark)
let directionRequest = MKDirections.Request()
directionRequest.source = sourceItem
directionRequest.destination = destItem
directionRequest.transportType = .any
let direction = MKDirections(request: directionRequest)
direction.calculate(completionHandler: {
response, error in
guard let response = response else {
if let error = error {
print(error.localizedDescription)
} else {
self.deliveryAnnotation.courseDegrees = self.getHeadingForDirectionFromCoordinate(self.kitchenAnnotation.coordinate, toLoc: self.userAnnotation.coordinate)
self.view.transform = CGAffineTransform(rotationAngle:CGFloat(self.deliveryAnnotation.courseDegrees))
}
return
}
guard let primaryRoute = response.routes.first else { return }
let route = response.routes[0]
self.mapView.addOverlay(route.polyline, level: .aboveRoads)
let rekt = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegion(rekt), animated: true)
})
//
UIView.animate(withDuration: Double(60), animations: {
self.deliveryAnnotation.coordinate = destinationCoordinate
}, completion: { success in
if success {
}
})
}
Your third annotation isn't following the route because you're animating it moving in a straight line between the first and second line. Try getting the coordinates from the MKRoute's polyline and animate between each one (According to apple's docs MKRoutes are made up of coordinates, but you might be able to use points as well)
If you'd like it to animate over the span of 60 seconds:
func moveDelivery(_ destinationCoordinate: CLLocationCoordinate2D) {
// I don't know why you have the delivery annotation start here, is this for testing?
deliveryAnnotation.coordinate = CLLocationCoordinate2DMake(29.959640, 31.270421)
let sourcePlaceMark = MKPlacemark(coordinate: destinationCoordinate)
let destPlaceMkark = MKPlacemark(coordinate: userAnnotation.coordinate)
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destPlaceMkark)
directionRequest.transportType = .any
let direction = MKDirections(request: directionRequest)
direction.calculate(completionHandler: {
response, error in
guard let response = response else {
print("MKRequest gave no response")
if let error = error {
print(error.localizedDescription)
} else {
self.deliveryAnnotation.courseDegrees = self.getHeadingForDirectionFromCoordinate(self.kitchenAnnotation.coordinate, toLoc: self.userAnnotation.coordinate)
self.view.transform = CGAffineTransform(rotationAngle:CGFloat(self.deliveryAnnotation.courseDegrees))
}
return
}
guard let primaryRoute = response.routes.first else {
print("response has no routes")
return
}
self.mapView.addOverlay(primaryRoute.polyline, level: .aboveRoads)
let rekt = primaryRoute.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegion(rekt), animated: true)
let coordinateArray = primaryRoute.polyline.coordinates
assert(coordinateArray.count > 0, "coordinate array is empty")
self.routeCoordinates = coordinateArray
// initiate recursive animations
self.coordinateIndex = 0
})
}
var routeCoordinates = [CLLocationCoordinate2D]()
var avgAnimationTime: Double {
return 60 / Double(routeCoordinates.count)
}
var coordinateIndex: Int! {
didSet {
guard coordinateIndex != routeCoordinates.count else {
print("animated through all coordinates, stopping function")
return
}
animateToNextCoordinate()
}
}
func animateToNextCoordinate() {
let coordinate = routeCoordinates[coordinateIndex]
UIView.animate(withDuration: avgAnimationTime, animations: {
self.deliveryAnnotation.coordinate = coordinate
}, completion: { _ in
self.coordinateIndex += 1
print("moved between coordinates")
})
}
EDIT
make sure to include this extension, otherwise you won't be able to get the coordinates of the MKRoute (source: https://gist.github.com/freak4pc/98c813d8adb8feb8aee3a11d2da1373f)
public extension MKMultiPoint {
var coordinates: [CLLocationCoordinate2D] {
var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid,
count: pointCount)
getCoordinates(&coords, range: NSRange(location: 0, length: pointCount))
return coords
}
}
EDIT #2
See above, edited original answer to animate through each coordinate after the previous finishes animating. Really rough but it should work.
EDIT #3
Added your code to get the destination variable as well as some assert and debug printing calls. If things aren't working this time, please tell me which debug messages you get.
EDIT #4
I just demo'd my code and it works. Here is the MapViewController class I used along with necessary extensions:
private let reuseId = "deliveryReuseId"
private let userTitle = "user"
private let startingPointTitle = "store"
private let deliveryTitle = "delivery truck"
class MapViewController: UIViewController {
var mapView: MKMapView!
// annotations for this demo, replace with your own annotations
var deliveryAnnotation: MKPointAnnotation = {
let annotation = MKPointAnnotation()
annotation.title = deliveryTitle
return annotation
}()
let userAnnotation: MKPointAnnotation = {
let annotation = MKPointAnnotation()
annotation.title = userTitle
annotation.coordinate = CLLocationCoordinate2DMake(29.956694, 31.276854)
return annotation
}()
let startingPointAnnotation: MKPointAnnotation = {
let annotation = MKPointAnnotation()
annotation.title = startingPointTitle
annotation.coordinate = CLLocationCoordinate2DMake(29.959622, 31.270363)
return annotation
}()
override func viewDidLoad() {
super.viewDidLoad()
loadMapView()
navigate()
}
func loadMapView() {
// set map
mapView = MKMapView()
view = mapView
mapView.delegate = self
mapView.register(MKAnnotationView.self, forAnnotationViewWithReuseIdentifier: reuseId)
// add annotations
mapView.addAnnotation(userAnnotation)
mapView.addAnnotation(startingPointAnnotation)
mapView.addAnnotation(deliveryAnnotation)
}
func navigate() {
let sourcePlaceMark = MKPlacemark(coordinate: startingPointAnnotation.coordinate)
let destPlaceMkark = MKPlacemark(coordinate: userAnnotation.coordinate)
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destPlaceMkark)
directionRequest.transportType = .any
let direction = MKDirections(request: directionRequest)
direction.calculate(completionHandler: { response, error in
if let error = error {
print(error.localizedDescription)
return
}
guard let primaryRoute = response!.routes.first else {
print("response has no routes")
return
}
self.mapView.addOverlay(primaryRoute.polyline, level: .aboveRoads)
self.mapView.setRegion(MKCoordinateRegion(primaryRoute.polyline.boundingMapRect), animated: true)
// initiate recursive animation
self.routeCoordinates = primaryRoute.polyline.coordinates
self.coordinateIndex = 0
})
}
var routeCoordinates = [CLLocationCoordinate2D]()
var avgAnimationTime: Double {
// to show delivery in 60 second, replace 60 with amount of seconds you'd like to show
return 60 / Double(routeCoordinates.count)
}
var coordinateIndex: Int! {
didSet {
guard coordinateIndex != routeCoordinates.count else {
print("animated through all coordinates, stopping function")
return
}
animateToNextCoordinate()
}
}
func animateToNextCoordinate() {
let coordinate = routeCoordinates[coordinateIndex]
UIView.animate(withDuration: avgAnimationTime, animations: {
self.deliveryAnnotation.coordinate = coordinate
}, completion: { _ in
self.coordinateIndex += 1
})
}
}
extension MapViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
// replace these images with your own
switch annotation.title {
case userTitle:
annotationView.image = UIImage(named: "user")
case startingPointTitle:
annotationView.image = UIImage(named: "store")
case deliveryTitle:
annotationView.image = UIImage(named: "deliveryTruck")
default: break
}
return annotationView
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard overlay is MKPolyline else {
return MKOverlayRenderer()
}
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .black
renderer.lineWidth = 5
renderer.lineJoin = .round
return renderer
}
}
public extension MKMultiPoint {
var coordinates: [CLLocationCoordinate2D] {
var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid,
count: pointCount)
getCoordinates(&coords, range: NSRange(location: 0, length: pointCount))
return coords
}
}
I have this func for populate pins on mapView:
func obervePins(){
let magRef = Database.database().reference().child("map")
magRef.observe(.value) { (snapshot) in
//var tempCoord = [CoordinatesOfMagazine]()
for child in snapshot.children {
if let chidSnapshot = child as? DataSnapshot,
let dictMag = chidSnapshot.value as? [String: Any],
let title = dictMag["Title"] as? String,
let latitude = dictMag["Latitude"] as? String,
let longitude = dictMag["Longitude"] as? String {
// let imageOfMagazine = dictMag["imageOfMagazine"] as? String,
// let url = URL(string: imageOfMagazine) {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: Double(latitude)!, longitude: Double(longitude)!)
annotation.title = title
print(annotation)
self.mapView.addAnnotations([annotation])
// let coordinates = CoordinatesOfMagazine(imageOfMagazine: url, Title: title)
// tempCoord.append(coordinates)
}
}
//self.coordinates = tempCoord
}
}
My data in Firebase looks like:
Pins in mapView is correct.
I don't know, how to display images for magazine in mapView. Help plz
Create a custom MKAnnotation class.
class ImageAnnotation : NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var imageOfMagazine: String?
override init() {
self.coordinate = CLLocationCoordinate2D()
self.title = nil
self.subtitle = nil
self.imageOfMagazine = nil
}
}
Set data and add the annotation to your mapView.
let annotation = ImageAnnotation()
annotation.coordinate = coordinate1
annotation.title = "title"
annotation.subtitle = "subtitle"
annotation.imageOfMagazine = imageOfMagazine
self.mapView.addAnnotation(annotation)
Implement mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) delegate method.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let annotation = annotation as? ImageAnnotation else {
return nil
}
let reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let data = NSData(contentsOf: URL(string: annotation.imageOfMagazine!)!)
pinView?.image = UIImage(data: data! as Data)
}
else {
pinView?.annotation = annotation
}
return pinView
}
// here take marker as global varible
var marker : GMSMarker?
self.ref.observe(.value) { snapshot in
let dict = snapshot.value as! NSDictionary
self.marker?.map?.clear()
if let lat = dict["latitude"] as? CLLocationDegrees ,let long = dict["longitude"] as? CLLocationDegrees {
var camera = GMSCameraPosition.camera(withLatitude: lat, longitude: longt, zoom: 12)
var position: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat, longt)
self.marker = GMSMarker(position: position)
self.marker?.icon = UIImage(named: imageName) // set your image here
self.marker?.map = self.mapview
self.mapview?.animate(to: camera)
}
}
I'm trying to make an app, where you get buses positions from web API. When I got the data, I put annotations on mapview for all of the coordinates i got from API. Then, when annotation is tapped on, I try to hide all the annotations which aren't on the same route as the one clicked. It works fine, but when I zoom out the annotations that weren't in the original region aren't hidden. Is there a way to refresh what is displayed when user zooms on map view?
import UIKit
import MapKit
import MBProgressHUD
import Alamofire
class MapViewController: UIViewController {
//MARK: Properties and Outlets
private var timer: NSTimer?
private lazy var dateFormatter = NSDateFormatter()
private var vehicles = [String: Vehicle]()
private var points = [CLLocationCoordinate2D]()
private let locationManager = CLLocationManager()
private var currentLocation: CLLocation?
#IBOutlet weak var mapView: MKMapView!
//MARK: Actions
#IBAction func getMyLocation(sender: UIBarButtonItem) {
getLocation()
}
//MARK: Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
dateFormatter.locale = NSLocale.currentLocale()
dateFormatter.dateFormat = "HH:mm:ss"
timer = NSTimer.scheduledTimerWithTimeInterval(30, target: self, selector: "fetchVehiclesLocations", userInfo: nil, repeats: true)
fetchVehiclesLocations()
getLocation()
}
//MARK: Get Location
private func getLocation() {
let authStatus = CLLocationManager.authorizationStatus()
if authStatus == .NotDetermined {
locationManager.requestWhenInUseAuthorization()
return
}
if authStatus == .Denied || authStatus == .Restricted {
showLocationServicesDeniedAlert()
return
}
startLocationManager()
}
//MARK: Helper methods
private func showLocationServicesDeniedAlert() {
let alert = UIAlertController(title: "Location Services Disabled", message: "Please enable location services for this app in Settings.", preferredStyle: .Alert)
let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alert.addAction(okAction)
presentViewController(alert, animated: true, completion: nil)
}
private func startLocationManager () {
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
showLoadingHUD()
}
}
private func stopLocationManager() {
locationManager.delegate = nil
locationManager.stopUpdatingLocation()
hideLoadingHUD()
}
private func rotateBus() {
UIView.animateWithDuration(1.0, delay: 0, options: .CurveLinear, animations: {
for (id, _) in self.vehicles {
if self.vehicles[id]!.lastPosition != nil {
let annotationView = self.mapView.viewForAnnotation(self.vehicles[id]!.annotation!)
let currentLocationPoint = self.mapView.convertCoordinate(self.vehicles[id]!.lastPosition!, toPointToView: self.mapView)
let destinationPoint = self.mapView.convertCoordinate(self.vehicles[id]!.coordinates, toPointToView: self.mapView)
let yDiff = currentLocationPoint.y - destinationPoint.y
let xDiff = destinationPoint.x - currentLocationPoint.x
let arcTan = atan(yDiff / xDiff)
var angle = CGFloat(M_PI / 2) - arcTan
if xDiff < 0 {
angle = angle + CGFloat(M_PI)
}
if angle.isNaN || angle == 0.0 {
continue
}
else {
annotationView?.transform = CGAffineTransformMakeRotation(CGFloat(angle))
}
}
}
}, completion: nil)
moveBus()
}
private func moveBus() {
UIView.animateWithDuration(28.0, delay: 0, options: .CurveLinear, animations: {
for(id, _) in self.vehicles {
if self.vehicles[id]!.lastPosition != nil {
self.vehicles[id]!.annotation?.coordinate = self.vehicles[id]!.coordinates
}
}
}, completion: nil)
}
private func createVehicles() {
print(vehicles.count)
for (id, _) in vehicles {
if vehicles[id]?.annotation == nil {
let annotation = BusAnnotation()
annotation.imageName = "bus"
annotation.coordinate = vehicles[id]!.coordinates
annotation.title = id
vehicles[id]?.annotation = annotation
mapView.addAnnotation(annotation)
}
}
print(mapView.annotations.count)
rotateBus()
}
private func drawPolyline() {
let myPolyline = MKPolyline(coordinates: &points, count: points.count)
mapView.addOverlay(myPolyline)
}
//MARK: HUD display methods
private func showLoadingHUD() {
let hud = MBProgressHUD.showHUDAddedTo(mapView, animated: true)
hud.labelText = "Getting Your Location..."
}
private func hideLoadingHUD() {
MBProgressHUD.hideAllHUDsForView(mapView, animated: true)
}
//MARK: Networking
func fetchVehiclesLocations() {
let URL = urlVehiclesLocations + apiKey
if !vehicles.isEmpty {
for (id , _) in vehicles {
vehicles[id]?.lastPosition = vehicles[id]?.coordinates
}
}
Alamofire.request(.GET, URL)
.validate()
.responseJSON {
(request, response, result) in
guard result.isSuccess else {
print("Error while fetching \(result.error!)")
return
}
let value = result.value as? [String: AnyObject]
let responseDict = value?["response"] as? [String: AnyObject]
let array = responseDict?["entity"] as? [[String: AnyObject]]
for var i = 0; i < array?.count; i++ {
let item = array?[i]["vehicle"] as? [String: AnyObject]
let position = item?["position"] as? [String: AnyObject]
let trip = item?["trip"] as? [String: AnyObject]
let vehicle = Vehicle()
vehicle.latitude = position?["latitude"] as! Double
vehicle.longitude = position?["longitude"] as! Double
vehicle.tripId = trip?["trip_id"] as! String
let startTime = trip?["start_time"] as! String
vehicle.startTime = self.dateFormatter.dateFromString(startTime)
let vehicleId = item?["vehicle"] as? [String: AnyObject]
let id = vehicleId?["id"] as! String
if self.vehicles[id] == nil {
self.vehicles[id] = vehicle
}
else {
self.vehicles[id]?.latitude = vehicle.latitude
self.vehicles[id]?.longitude = vehicle.longitude
}
}
self.createVehicles()
}
}
func fetchPointsForTripPolyline() {
let URL = urlTripPolyline + apiKey
Alamofire.request(.GET, URL)
.validate()
.responseJSON {
(request, response, result) in
guard result.isSuccess else {
print("Error while fetching \(result.error!)")
return
}
let value = result.value as! [String: AnyObject]
let responseArray = value["response"] as! [[String: AnyObject]]
for var i = 0; i < responseArray.count; i++ {
let longitude = responseArray[i]["shape_pt_lon"] as! CLLocationDegrees
let latitude = responseArray[i]["shape_pt_lat"] as! CLLocationDegrees
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
self.points.append(coordinate)
}
self.drawPolyline()
}
}
}
extension MapViewController: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let newLocation = locations.last!
if newLocation.timestamp.timeIntervalSinceNow < -5 {
return
}
if newLocation.horizontalAccuracy < 0 {
return
}
if newLocation.horizontalAccuracy <= locationManager.desiredAccuracy {
stopLocationManager()
currentLocation = newLocation
let annotation = MKPointAnnotation()
annotation.coordinate = newLocation.coordinate
mapView.addAnnotation(annotation)
}
let center = CLLocationCoordinate2D(latitude: newLocation.coordinate.latitude, longitude: newLocation.coordinate.longitude)
let region = MKCoordinateRegionMakeWithDistance(center, 1000, 1000)
self.mapView.setRegion(region, animated: true)
}
}
extension MapViewController: MKMapViewDelegate {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is BusAnnotation) {
return nil
}
let reuseId = annotation.title!
var busAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId!)
if busAnnotationView == nil {
busAnnotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
busAnnotationView?.canShowCallout = true
}
else {
busAnnotationView?.annotation = annotation
}
let busAnnotation = annotation as! BusAnnotation
busAnnotationView?.image = UIImage(named: busAnnotation.imageName)
return busAnnotationView
}
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let lineView = MKPolylineRenderer(overlay: overlay)
lineView.lineWidth = 3.0
lineView.strokeColor = UIColor.greenColor()
return lineView
}
return MKOverlayRenderer()
}
func hideBuses(tripId: String) {
for (_, vehicle) in vehicles {
if vehicle.tripId != tripId {
let annotationView = mapView.viewForAnnotation(vehicle.annotation!)
annotationView?.hidden = true
}
}
}
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
let vehicleId = view.annotation?.title!
let tripId = vehicles[vehicleId!]?.tripId
hideBuses(tripId!)
}
}
I am trying to add custom images to my mapView but am not having any luck so far. I keep getting a SIGABRT error when the map is loaded. here is my code:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(NiteOwlAnnotations) {
let reuseId = "test"
var annoView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if annoView == nil {
annoView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
annoView?.image = UIImage(named: "bar-map-icon")
annoView?.canShowCallout = true
} else {
annoView?.annotation = annotation
}
return annoView
/* let annoView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "Default")
// change color of pins.
annoView.pinTintColor = UIColor.blackColor()
annoView.animatesDrop = false
annoView.image = UIImage(named: "bar-map-icon")
annoView.backgroundColor = UIColor.clearColor()
annoView.canShowCallout = true
return annoView
*/
} else if annotation.isKindOfClass(MKUserLocation) {
return nil
}
return nil
}// end func
//--------------------------------------------------------------
func createAnnotationForLocation(location: CLLocation) {
let niteOwl = NiteOwlAnnotations(coordinate: location.coordinate)
map.addAnnotation(niteOwl)
}
I have looked for more information on this and still no luck yet:
Change pin image on MKMapView in Swift