I would like to add a pin on the Map with an image on a gesture.
Actually the add pin on gesture feature works great but without the image because it has to be a MKAnnotationView and not just MKAnnotation.
So I got weird warnings that I'm unable to fix:
override func viewDidLoad() {
super.viewDidLoad()
let annotation = MKPointAnnotation()
annotation.title = location.title
annotation.coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
mapView.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
let identifier = "CustomAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = false
annotationView?.backgroundColor = UIColor.clear
annotationView!.image = UIImage(named: "map-pinpoint.png")!
} else {
annotationView!.annotation = annotation
}
return annotationView
}
Maybe the errors are because MKPinAnnotationView always use a pin image, so you can't be override. You should use MKAnnotationView instead.
Related
so I am using MapKit for the first time and I am trying to show annotations with a callout.
The annotations appear but as soon as I add the delegate function viewFor annotation (func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {}) the annotations do not appear anymore. Is there anything I am missing in that function ?
Edit
I forgot to mention that the View Controller is the delegate of MKMapViewDelegate
#objc func addAnnotationOnLongPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == .ended {
let point = gesture.location(in: self.mapView)
let coordinate = self.mapView.convert(point, toCoordinateFrom: self.mapView)
//Now use this coordinate to add annotation on map.
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
usf.fetchJSON(urlString: usf.setNewLocation(lat: annotation.coordinate.latitude, lon: annotation.coordinate.longitude)) { (data, success) in
if success {
annotation.title = data?.name
annotation.subtitle = "HAa"
} else {
let alertUI = self.usf.createAlertOK(title: "Something went wrong!", message: "Cannot get the current weather! \n Check your connectivity or try again later")
self.present(alertUI, animated: true, completion: nil)
}
}
let previousAnnotations = self.mapView.annotations
if !previousAnnotations.isEmpty{
self.mapView.removeAnnotation(previousAnnotations[0])
}
self.mapView.addAnnotation(annotation)
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
print("in viewFor annotation") // prints out
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "TempAnnotationView")
annotationView.canShowCallout = true
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
self.mapView.showAnnotations(mapView.annotations, animated: false)
return annotationView
}
You are instantiating a MKAnnotationView. If you have some custom image, then set the image property of this MKAnnotationView. Or, easier, just use MKPinAnnotationView or MKMarkerAnnotationView instead.
And as Sh_Kahn noted, make sure you create you annotation inside the closure, not after it.
You need
if success {
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = data?.name
annotation.subtitle = "HAa"
self.mapView.addAnnotation(annotation)
}
The api that gets name is asynchronous so you have to add the filled annotation inside the callback
I'm trying to add a custom image for my pin annotations as well as change the colour of the custom images for some of the annotations. The colour is changed. However, the image doesn't show up. The default pins show instead.
Here's my code:
class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?
}
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate{
#IBOutlet weak var map: MKMapView!
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
if annotation is MKUserLocation {
return nil
}
if let annotation = annotation as? MyPointAnnotation {
annotationView?.pinTintColor = annotation.pinTintColor
annotationView?.image = UIImage(named: "BLog.png")
}
return annotationView
}
override func viewDidLoad() {
super.viewDidLoad()
self.map.delegate = self
let annotation1 = MyPointAnnotation()
annotation1.coordinate = CLLocationCoordinate2DMake([LatArray], [LonArray])
annotation1.title = NameArray
annotation1.pinTintColor = .red
let annotation2 = MyPointAnnotation()
annotation2.coordinate = CLLocationCoordinate2DMake([LatArray2], [LonArray2])
annotation2.title = NameArray2
annotation2.pinTintColor = .green
}
}
The image "BLog.png" is located in the main bundle.
I've assigned the MKMapView as a delegate.
But the image still won't change.
You need to use MKAnnotationView instead of MKPinAnnotationView to add a custom image for your pin annotations.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if // Image pin // {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "image")
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "image")
annotationView?.canShowCallout = true
annotationView?.image = UIImage(named: "BLog.png")
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
annotationView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
annotationView?.annotation = annotation
}
return annotationView
} else {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
annotationView?.pinTintColor = annotation.pinTintColor
}
return annotationView
}
}
I'm trying to change the colour of my annotation pins. However, I am wanting it to change the colour of the new Apple annotation logo. Instead, when the colours change, the new logo (as shown below) converts to the old logo (as shown below).
Is there anyway to change the colour as well as keep the new annotation pin?
Here's my code:
class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
if annotation is MKUserLocation {
return nil
}
if let annotation = annotation as? MyPointAnnotation {
annotationView?.pinTintColor = annotation.pinTintColor
}
return annotationView
}
self.map.delegate = self
/// in view did load
Old pin:
New pin:
any input would be greatly appreciated!
Use MKMarkerAnnotationView instead of MKPinAnnotationView.
if annotationView == nil {
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
MKMarkerAnnotationView uses markerTintColor rather than pinTintColor.
However, this only works on iOS 11.
The new icon is only present in iOS 11.
I am creating a map which contains both custom annotation pins as well as images in the annotation callouts. The only problem is that I cannot figure out a way to have different images for different annotations. More specifically, I'm after having individual images for the annotation callouts. While I have found results on how to change the pin, I am struggling with finding any info for the callout and would appreciate any help. Below is the function for the annotations I am working with. Thank you.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil}
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: "pinAnnotation.png")
}
let imageName = "until.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
annotationView?.detailCalloutAccessoryView = imageView
return annotationView
}
class ViewController2: UIViewController {
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
//Location for first Pin
let locationOne = CLLocationCoordinate2DMake(-47.016945, 167.852095)
//Location for map centering
let locationNZ = CLLocationCoordinate2DMake(-43.937462, 170.507813)
let span = MKCoordinateSpanMake(9, 9)
let region = MKCoordinateRegion(center: locationNZ, span: span)
mapView.setRegion(region, animated: true)
//Create annotation one
let annotation = MKPointAnnotation()
annotation.coordinate = locationOne
annotation.subtitle = "Park"
annotation.title = "Rakiura National Park"
//Add annotation to the map
mapView.addAnnotation(annotation)
mapView.delegate = self}
I have created a map which contains a single annotation. From what I've seen, this is a very simple way of achieving this which I got off a tutorial. I am currently trying to get a custom picture as the annotation but am struggling to do so as almost all information on this topic is in objective C. Forgive me if it is really simple to do but I am relatively new to coding and would appreciate any help :)
class ViewController2: UIViewController {
#IBOutlet var Map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Location for first Pin
let locationOne = CLLocationCoordinate2DMake(-47.016945, 167.852095)
//Location for map centering
let locationNZ = CLLocationCoordinate2DMake(-43.937462, 170.507813)
let span = MKCoordinateSpanMake(9, 9)
let region = MKCoordinateRegion(center: locationNZ, span: span)
Map.setRegion(region, animated: true)
//Create annotation one
let annotation = MKPointAnnotation()
annotation.coordinate = locationOne
annotation.subtitle = "Park"
annotation.title = "Rakiura National Park"
//Add annotation to the map
Map.addAnnotation(annotation)}
I assume its a different image of the default pin you want?
I've used this answer from another question, check it out here
Custom pin image in annotationView in iOS
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
}
updating #Jonask's answer
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.isKind(of: MKUserLocation.self) else {
return nil
}
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
}