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
}
Related
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.
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 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'm using MapKit and I'm currently trying to set a custom pin annotation image on my pins. However, I'm having a hard time figuring out why it doesn't work. All of the other code is working perfectly, and when I try printing the frame of the image after setting it, it does show the correct dimensions for my "pinImage", so it seems to be able to set the image on the property.
Also, the delegate is set correctly, this is verified by setting a custom color on the default pin.
I've also tried using "pinImage.png", without luck. And since MKPinAnnotationView is a subclass of MKAnnotationView, I see no problem with why that should be the issue, and to be sure, I tried to use the MKAnnotationView also, without luck.
Here's my code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? Pin {
let identifier = LocalConstants.pinIdentifier
var view: MKPinAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
let detailButton = UIButton(type: .detailDisclosure) as UIView
view.rightCalloutAccessoryView = detailButton
//view.pinTintColor = Util.Colors.pluppPurple
}
view.image = UIImage(named: "pinImage")
return view
}
Thanks in advance!
The answer was indeed to use MKAnnotationView and not MKPinAnnotationView. I do not know what I messed up when trying it out yesterday. Final working copy below, for future reference:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? Pin {
let identifier = LocalConstants.pinIdentifier
var view: MKAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
view = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.tintColor = Util.Colors.pluppGrey
let detailButton = UIButton(type: .detailDisclosure) as UIView
view.rightCalloutAccessoryView = detailButton
}
view.image = UIImage(named: LocalConstants.pluppPin)
return view
}
return nil
}
I am creating a map application which allows emojis to be attached to locations. Currently, the image is displayed above the stock apple map annotation.
I wish to hide the stock pin image while still displaying the selected emoji by the user. Is this possible?
I have this code so far to perform this:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
//let identifier = "MyPin"
if annotation.isKindOfClass(MKUserLocation) {
return nil
}
let dictName = arrLocation[((annotation as? MyAnnotation)?.index)!]
let imgName = dictName.valueForKey("pin_img") as? String
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(imgName!)
if annotationView == nil
{
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: imgName)
annotationView!.canShowCallout = false
let name = dictName.valueForKey("name") as! String
let annot = MyAnnotation(titleName:name)
annotationView?.annotation = annot
}
else
{
annotationView!.annotation = annotation
}
let detailButton: UIButton = UIButton(type: UIButtonType.Custom)
// size and placement of emoji on map
detailButton.frame = CGRectMake(-34,-25,85,85)
detailButton.tag = ((annotation as? MyAnnotation)?.index)!
detailButton.addTarget(self, action:"emojiTap:", forControlEvents: UIControlEvents.TouchUpInside)
detailButton.setBackgroundImage(UIImage(named:(dictName.valueForKey("pin_img") as? String)!), forState: UIControlState.Normal)
annotationView!.addSubview(detailButton)
return annotationView
}
Custom annotation view
Instead of using an MKPinAnnotationView, use its superclass MKAnnotationView.
Responding to input
To respond to the user tapping on an annotation implement the mapView:didSelectAnnotation: delegate method. This delegate method is called when the annotation is tapped.
Note that you do not need to use the button inside the annotation view. This means the functionality in emojiTap: must be implemented by the mapView:didSelectAnnotationMethod:.
Example
Combining these
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(MKUserLocation) {
return nil
}
let dictName = arrLocation[((annotation as? MyAnnotation)?.index)!]
let imgName = dictName.valueForKey("pin_img") as? String
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(imgName!)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: imgName)
let name = dictName.valueForKey("name") as! String
let annot = MyAnnotation(titleName:name)
annotationView?.annotation = annot
}
else
{
annotationView!.annotation = annotation
}
annotationView!.canShowCallout = false
return annotationView
}
func mapView(_ mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
guard let annotation = view.annotation as? MyAnnotation else {
return
}
print("tapped annotation: \(annotation.index)
// Implement the code from emojiTap: here.
}