How to add custom images to annotations in Mapview Swift ios? - ios

var lat:CLLocationDegrees = 40.748708
var long:CLLocationDegrees = -73.985643
var latDelta:CLLocationDegrees = 0.01
var longDelta:CLLocationDegrees = 0.01
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat, long)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
mapView.setRegion(region, animated: true)
var information = MKPointAnnotation()
information.coordinate = location
information.title = "Test Title!"
information.subtitle = "Subtitle"
mapView.addAnnotation(information)
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is MKPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView?.image = UIImage(named:"annotation")
anView?.canShowCallout = true
}
else {
anView?.annotation = annotation
}
return anView
}
I need to load custom image for the annotation in Mapview. I have an image named "Annotation" and I am trying to call it in viewfor annotation method. How can I achieve this?

Here is the answer:
Swift 4:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}
Swift 3:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}
Swift 2.2:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}

Swift 4.0
var coordinates: [[Double]]!
var addresses:[String]!
In viewDidload() add following code to add annotations to MapvView.
coordinates = [[28.4344,72.5401],[28.85196,72.3944],[28.15376,72.1953]]// Latitude,Longitude
addresses = ["Address1","Address2","Address3"]
self.mapView.delegate = self // set MapView delegate to self
for i in 0...2 {
let coordinate = coordinates[i]
let point = CustomAnnotation(coordinate: CLLocationCoordinate2D(latitude: coordinate[0] , longitude: coordinate[1] )) // CustomAnnotation is class and pass the required param
point.address = addresses[i] // passing only address to pin, you can add multiple properties according to need
self.mapView.addAnnotation(point)
}
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 28.856614, longitude: 72.3522219), span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
self.mapView.setRegion(region, animated: true)
Add new class having name CustomAnnotation inherited from MKAnnotation for our custom annotation
import MapKit
class CustomAnnotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var address: String!
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
}
}
Add one more class having name AnnotationView inherited from MKAnnotationView. I am showing custom callout so it it is required to to override the overridefuncpoint() method to receive touch in custom callout view.
import MapKit
class AnnotationView: MKAnnotationView
{
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
if (hitView != nil)
{
self.superview?.bringSubview(toFront: self)
}
return hitView
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let rect = self.bounds;
var isInside: Bool = rect.contains(point);
if(!isInside)
{
for view in self.subviews
{
isInside = view.frame.contains(point);
if isInside
{
break;
}
}
}
return isInside;
}
}
Now implement viewForannotation MapView delegate as follow
extension YourViewC: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation
{
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "CustomPin")
if annotationView == nil{
annotationView = AnnotationView(annotation: annotation, reuseIdentifier: "CustomPin")
annotationView?.canShowCallout = false
}else{
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "bluecircle") // Pass name of your custom image
return annotationView
}
func mapView(_ mapView: MKMapView,
didSelect view: MKAnnotationView){
let annotation = view.annotation as? CustomAnnotation
print(annotation?.address) // get info you passed on pin
// write code here to add custom view on tapped annotion
}

The best way to achieve this is using custom class to store annotations.
import UIKit
import MapKit
import CoreLocation
class Annotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D()
var title: String?
var subtitle: String?
var strTitle = ""
var strImgUrl = ""
var strDescr = ""
init(coordinates location: CLLocationCoordinate2D, title1: String, description: String, imgURL: String) {
super.init()
coordinate = location
title = title1
subtitle = description
strTitle = title1
strImgUrl = imgURL
strDescr = description
}
}
Now use this class to store annotation and populate your pins.
// MapViewController.swift
let myAnnotation1: Annotation = Annotation.init(coordinates: CLLocationCoordinate2D.init(latitude: 30.733051, longitude: 76.763042), title1: "The Mayflower Renaissance Hotel", description: "The Histroic hotel has been the site of saveral dramatic locations.", imgURL: "custom.jpg")
self.uvMApView.addAnnotation(myAnnotation1)
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation is MKUserLocation) {
return nil
}
// try to dequeue an existing pin view first
let AnnotationIdentifier = "AnnotationIdentifier"
let myAnnotation1 = (annotation as! Annotation)
let pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: AnnotationIdentifier)
pinView.canShowCallout = true
pinView.image = UIImage(named: myAnnotation1. strImgUrl)!
return pinView
}

After spending lot of time, i came up with a simple code.
1. Don't use .pdf images, use only .png images with three different sizes such as 1x, 2x, 3x. Below is my sample code.
#IBOutlet var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
mapViewSetup()
}
func mapViewSetup(){
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
mapView.showsUserLocation = false
if let coor = mapView.userLocation.location?.coordinate{
mapView.setCenter(coor, animated: true)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
mapView.mapType = MKMapType.standard
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: locValue, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = locValue
annotation.title = "Arshad"
annotation.subtitle = "BrightSword Technologies Pvt Ltd"
mapView.addAnnotation(annotation)
self.locationManager.stopUpdatingLocation()
//centerMap(locValue)
}
private func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print(error.localizedDescription)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customannotation")
annotationView.image = UIImage(named: "icon_location_pin")
annotationView.canShowCallout = true
return annotationView
}
Hope it will help someone.

You can also do like this:
let reuseId = "pin"
var your_pin = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
let your_image = UIImage (named: "your_image")
pinView?.image = your_image
pinView?.canShowCallout = true
I think it is the more easily answer.

Related

How to generate different pins on mapview in Swift 3?

I am coming to a problem where I try to generate different icons to show on the map view of places. But, I need some help from you guys. So far, I have hard-coded a pin to show on the map view. I also, have different pins in my assets, I want to show them by generating it on the mapview. How can I generate different icons to show on my map view from the API? Thanks for the help.
Here is my code:
import UIKit
import MapKit
import CoreLocation
class MapViewController: BaseViewController{
#IBOutlet weak var leadingConstraints: NSLayoutConstraint!
#IBOutlet weak var menuView: UIView!
#IBOutlet weak var mapView: MKMapView!
fileprivate let locationManager = CLLocationManager()
fileprivate var startedLoadingPOIs = false
fileprivate var places = [Place]()
fileprivate var arViewController: ARViewController!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var nearMeIndexSelected = NearMeIndexTitle()
var menuShowing = false
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
//making shadow of our menu view
menuView.layer.shadowOpacity = 1
menuView.layer.shadowRadius = 7
}
#IBAction func showARController(_ sender: Any) {
arViewController = ARViewController()
arViewController.dataSource = self
arViewController.maxVisibleAnnotations = 30
arViewController.headingSmoothingFactor = 0.05
arViewController.setAnnotations(places)
self.navigationController!.pushViewController(arViewController, animated: true)
}
}
extension MapViewController: CLLocationManagerDelegate, MKMapViewDelegate {
// // Changing the Pin Color on the map.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
mapView.tintColor = #colorLiteral(red: 0.8823529412, green: 0.1647058824, blue: 0.1333333333, alpha: 1)
return nil
} else {
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
let pin = mapView.view(for: annotation) ?? MKAnnotationView(annotation: annotation, reuseIdentifier: nil)
pin.image = UIImage(named: "pins")
return pin
return annotationView
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if locations.count > 0 {
let location = locations.last!
print("Accuracy: \(location.horizontalAccuracy)")
if location.horizontalAccuracy < 100 {
manager.stopUpdatingLocation()
let span = MKCoordinateSpan(latitudeDelta: 0.013, longitudeDelta: 0.013)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.region = region
if !startedLoadingPOIs {
DispatchQueue.main.async {
self.activityIndicator.startAnimating()
}
startedLoadingPOIs = true
let loader = PlacesLoader()
loader.loadPOIS(location: location, radius: 1500) { placesDict, error in
if let dict = placesDict {
guard let placesArray = dict.object(forKey: "results") as? [NSDictionary] else { return }
for placeDict in placesArray {
let latitude = placeDict.value(forKeyPath: "geometry.location.lat") as! CLLocationDegrees
let longitude = placeDict.value(forKeyPath: "geometry.location.lng") as! CLLocationDegrees
let reference = placeDict.object(forKey: "reference") as! String
let name = placeDict.object(forKey: "name") as! String
let address = placeDict.object(forKey: "vicinity") as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let place = Place(location: location, reference: reference, name: name, address: address)
self.places.append(place)
let annotation = PlaceAnnotation(location: place.location!.coordinate, title: place.placeName)
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
self.mapView.isHidden = false
}
}
}
}
}
}
}
}
You can compare the coordinate of the annotation and specify custom pin for that Annotation.
if annotation.coordinate == "Your Custom Pin Coordinate" { //set custom pin }
Suppose I want to add a custom pin for my selected Place.
var selectedPlace: PlaceAnnotation
Inside your loop. suppose my selected place is "toronto"
if name == "toronto" { self.selectedPlace = annotation }
Then in ViewForAnnotation method
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.coordinate = selectedPlace.coordinate {
pin.image = UIImage(named: "YOUR SELECTED IMAGE")
}
}
See here my demo to create a custom pin view customPinAnnotationButton
Here is the method to draw annotation with image , I subclassed MKAnoationView
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MyAnnotation == false
{
return nil
}
let senderAnnotation = annotation as! MyAnnotation
let pinReusableIdentifier = senderAnnotation.pinColor.rawValue
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pinReusableIdentifier)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: senderAnnotation, reuseIdentifier: pinReusableIdentifier)
annotationView!.canShowCallout = false
}
if senderAnnotation.pinColor == PinColor.Green
{
let pinImage = UIImage(named:"directMarker3.png")
annotationView!.image = pinImage
}
return annotationView
}
here to add an annotation
let blueLocation = CLLocationCoordinate2D(latitude:30.45454554, longitude: 29.646727)
let blueAnnotation = MyAnnotation(coordinate: blueLocation, title:"ghghhg",subtitle: "hgnhhghghg",pinColor: .Green ,uid:"hghg",type:"provider")
self.mymap.addAnnotation(blueAnnotation)
self.mymap.showAnnotations(self.mymap.annotations, animated: true)
1.Define subclass of MKPointAnnotation:
class MyPointAnnotation: MKPointAnnotation {
var imageName: String = ""
}
2.Set image name.
let annotation = MyPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "title"
annotation.subtitle = "subtitle"
annotation.imageName = "pin" // Set image name here
self.mapView.addAnnotation(annotation)
3.Load image in viewFor delegate method
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "image"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let annotation = annotation as! MyPointAnnotation
pinView?.image = UIImage(named: annotation.imageName)
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}

Custom Annotation Using MKPointAnnotation

This what I'm trying to do:
Use a single custom annotation for all the locations that will populate the map. I have the custom image saved in the assets but, can't make it work.
My code is as follows:
ViewDidLoad()
if let locationDict = snap.value as? Dictionary<String, AnyObject> {
let lat = locationDict["LATITUDE"] as! CLLocationDegrees
let long = locationDict["LONGITUDE"] as! CLLocationDegrees
let title = locationDict["NAME"] as! String
let center = CLLocationCoordinate2D(latitude: lat, longitude: long)
_ = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.10, longitudeDelta: 0.10))
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(lat, long)
annotation.title = title.capitalized // if you need title, add this line
self.mapView.addAnnotation(annotation)
}
Use a single custom annotation for all the locations that will populate the map. I have the custom image saved in the assets but, can't make it work (Details in the viewDidLoad)
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView: MKAnnotationView?
if annotation.isKind(of: MKUserLocation.self) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "User")
annotationView?.image = UIImage(named: "icon")
}
return annotationView
}
You should implement delegate method:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKind(of: MKUserLocation.self) {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "User")
annotationView.image = UIImage(named: "icon")
return annotationView
}
let reuseId = "Image"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
annotationView?.canShowCallout = true
annotationView?.image = UIImage(named: "<<image name>>")
}
else {
annotationView?.annotation = annotation
}
return annotationView
}
You should implement delegate method like this.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var pinView : MKAnnotationView? = nil
let identifer = "pin"
pinView = mapView .dequeueReusableAnnotationView(withIdentifier: identifer)
if pinView == nil {
pinView = MKAnnotationView.init(annotation: annotation, reuseIdentifier: identifer)
}
pinView?.canShowCallout = true
pinView?.calloutOffset = CGPoint(x: -5, y: 5)
pinView?.rightCalloutAccessoryView = UIButton.init(type: .detailDisclosure) as UIView
let type = (annotation as! CustomAnnotation).type
if type == -1 {
pinView?.image = UIImage(named: "Img_gray_pin")?.resized(toWidth: 20)
} else if type == 0 {
pinView?.image = UIImage(named: "Img_gray_pin")?.resized(toWidth: 20)
} else if type == 1{
pinView?.image = UIImage(named: "Img_blue_pin")?.resized(toWidth: 20)
} else if type == 2 {
pinView?.image = UIImage(named: "Img_orange_pin")?.resized(toWidth: 25)
} else if type == 3 {
pinView?.image = UIImage(named: "Img_red_pin")?.resized(toWidth: 30)
} else {
pinView?.image = UIImage(named: "Img_gray_pin")?.resized(toWidth: 20)
}
return pinView
}
And then create CustomAnnotation Class
import MapKit
import UIKit
class CustomAnnotation: NSObject, MKAnnotation {
let title: String?
let subtitle: String?
let coordinate: CLLocationCoordinate2D
let tag : Int
let type : Int
init(title: String, address: String, coordinate: CLLocationCoordinate2D, tag : Int, type : Int) {
self.title = title
self.subtitle = address
self.coordinate = coordinate
self.tag = tag
self.type = type
super.init()
}
}

How to set identifier in MKPointAnnotation

I am trying to make a lot different type of annotation. All annotation need to customize for the beautiful reason.
I know that it need to use viewFor Annotation, but how can I know what kind of the annotation?
func addZoneAnnotation() {
let zoneLocations = ZoneData.fetchZoneLocation(inManageobjectcontext: managedObjectContext!)
for zoneLocation in zoneLocations! {
let zoneCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: Double(zoneLocation["latitude"]!)!, longitude: Double(zoneLocation["longitude"]!)!)
let zoneAnnotation = MKPointAnnotation()
zoneAnnotation.coordinate = zoneCoordinate
map.addAnnotation(zoneAnnotation)
}
}
Subclass MKPointAnnotation to add whatever property that you want:
class MyPointAnnotation : MKPointAnnotation {
var identifier: String?
}
Then you can use it as follow:
func addZoneAnnotation() {
let zoneLocations = ZoneData.fetchZoneLocation(inManageobjectcontext: managedObjectContext!)
for zoneLocation in zoneLocations! {
let zoneCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: Double(zoneLocation["latitude"]!)!, longitude: Double(zoneLocation["longitude"]!)!)
let zoneAnnotation = MyPointAnnotation()
zoneAnnotation.coordinate = zoneCoordinate
zoneAnnotation.identifier = "an identifier"
map.addAnnotation(zoneAnnotation)
}
}
And finally when you need to access it:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let annotation = annotation as? MyPointAnnotation else {
return nil
}
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "reuseIdentifier")
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "reuseIdentifier")
} else {
annotationView?.annotation = annotation
}
// Now you can identify your point annotation
if annotation.identifier == "an identifier" {
// do something
}
return annotationView
}

Swift MapKit: Parsing data to next VC from annotationView

Is there a way to parse an array of information to the next VC when the users tap the rightCalloutAccessoryView?
Lets say I have this set of information that I need to parse over:
[name: "XXX",gender: "YYY",lat: 11.1111,lon: 22.2222]
and in the next VC we will display these info in a 'profile page' manner. My implementation thus far is as such:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "pin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
annotationView?.canShowCallout = true
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
} else {
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "PersonIcon")
return annotationView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
viewActivity()
}
}
func viewActivity() {
let controller = storyboard?.instantiateViewController(withIdentifier: "ActivityView") as! ActivityViewController
controller.parsedInfo = /*parsedInfo*/
navigationController?.pushViewController(controller, animated: true)
}
EDIT:
Code for addAnnotation in viewDidLoad:
FIRHelperClient.sharedInstance.getLocationsForActivities(ref) { (results, error) in
if let error = error {
print(error.localizedDescription)
} else {
for result in results! {
guard let lat = result.lat, let lon = result.lon, let activity = result.searchActivities else {
print("locationForActivities did not return lat or lon")
return
}
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
annotation.title = activity
self.mapView.addAnnotation(annotation)
}
}
}

show custom annotation in mapkit

I'm trying to show an image annotation instead of a pin annotation on the mapkit. I'm using this code:
import UIKit
import MapKit
class ViewController2: UIViewController , MKMapViewDelegate {
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
let coordinate = CLLocationCoordinate2DMake(26.889281, 75.836042)
let region = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
var info1 = CustomPointAnnotation()
info1.coordinate = CLLocationCoordinate2DMake(26.889281, 75.836042)
info1.title = "Info1"
info1.subtitle = "Subtitle"
info1.imageName = "taxi"
var info2 = CustomPointAnnotation()
info2.coordinate = CLLocationCoordinate2DMake(26.862280, 75.815098)
info2.title = "Info2"
info2.subtitle = "Subtitle"
info2.imageName = "smile"
mapView.addAnnotation(info1)
mapView.addAnnotation(info2)
mapView.showAnnotations(mapView.annotations, animated: true)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
print("delegate called")
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView?.canShowCallout = true
}
else {
anView?.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as! CustomPointAnnotation
anView?.image = UIImage(named:cpa.imageName)
return anView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
}
}
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
}
I think this method is not calling viewForAnnotation, although I connect the delegate with viewcontroller : mapView.delegate = self.
I still see the pin annotation instead of custominnotation on the map:
now when implement this code :
import UIKit
import MapKit
class ViewController2: UIViewController , MKMapViewDelegate {
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
let coordinate = CLLocationCoordinate2DMake(26.889281, 75.836042)
let region = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.title = "Annotation Created"
annotation.subtitle = "mahdi"
annotation.coordinate = CLLocationCoordinate2DMake(26.889281, 75.836042)
let annotation2 = MKPointAnnotation()
annotation2.title = "Annotation Created"
annotation2.subtitle = "mahdi"
annotation2.coordinate = CLLocationCoordinate2DMake(26.862280, 75.815098)
mapView.addAnnotation(annotation)
mapView.addAnnotation(annotation2)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "taxi")
return annotationView
}
i can see the two images annotations like this :
enter image description here
now i want to include this image with user location , i try with this code but still see the red pin annotation instead of image
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = manager.location?.coordinate {
userLocation = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
// print(userLocation)
if driverOnTheWay == false {
let region = MKCoordinateRegion(center: userLocation, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
self.mapView.removeAnnotations(self.mapView.annotations)
let annotation = MKPointAnnotation()
annotation.title = "مكانك هنا"
annotation.subtitle = "mahdi"
annotation.coordinate = userLocation
self.mapView.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "car")
return annotationView
}
how can show car image with user location

Resources