The annotation is displayed in my map but I can't add a callout. I am planing to use the callout to change a label.text to the title of the annotation in the same ViewController.
I tried this for example but what am I missing to make it work.
I hope somebody can help me out since this problem I could solve everything with stackoverflow or youtube but I am trying for hours now :(
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
map.delegate = self
let cor : CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 50, longitude: 10)
let region = MKCoordinateRegionMakeWithDistance(cor, 5000, 5000)
self.map.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate.latitude = 50
annotation.title = "test"
annotation.subtitle = "hdhsadsa"
annotation.coordinate.longitude = 10
map.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "identifier") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "identifier")
annotationView?.canShowCallout = true
annotationView?.rightCalloutAccessoryView = UIButton(type: .infoLight)
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
Related
I believe this is going to be a really easy answer but I've been trying to figure out how I add a custom callout view with map views default pins. With my current code it seems I can only add an image as the MKPointAnnotation instead of the default pins. This first "viewFor annotation" is how I set up the default pins, while everything underneath is for the custom call out view... What I am trying to do is have my custom call out view with the default pins. Do I have to add a custom image pin if I want a custom call out view?
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "") {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:"")
annotationView.isEnabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil{
annotationView = CustomBusinessCallOutAnnotatiion(annotation: annotation, reuseIdentifier: "Pin")
annotationView?.canShowCallout = false
}else{
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "car")
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if view.annotation is MKUserLocation { return }
let customAnnotation = view.annotation as! CustomBusinessPoint
let views = Bundle.main.loadNibNamed("CustomBusinessCallOut", owner: nil, options: nil)
let calloutView = views?[0] as! CustomBusinessCallOut
calloutView.businessName.text = customAnnotation.businessName
calloutView.businessStreet.text = customAnnotation.businessStreet
calloutView.businessState.text = customAnnotation.businessState
calloutView.businessDistance.text = customAnnotation.businessDistance
calloutView.center = CGPoint(x: view.bounds.size.width / 2, y: -calloutView.bounds.size.height * -0.0001)
view.addSubview(calloutView)
mapView.setCenter((view.annotation?.coordinate)!, animated: true)
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
if view.isKind(of: CustomBusinessCallOutAnnotatiion.self) {
for subview in view.subviews {
subview.removeFromSuperview()
}
}
}
You need not addSubView calloutView. You can use MKAnnotationView as Custom Callout.
e.g. You should arrange the source code
Implement subclass of MKAnnotation and MKAnnotationView.
class PinAnnotation : NSObject, MKAnnotation {
var coordinate : CLLocationCoordinate2D
var title: String?
var calloutAnnotation: CustomBusinessCallOut?
init(location coord:CLLocationCoordinate2D) {
self.coordinate = coord
super.init()
}
}
class CustomBusinessCallOut : NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
init(location coord:CLLocationCoordinate2D) {
self.coordinate = coord
super.init()
}
}
class CalloutAnnotationView : MKAnnotationView {
}
Implement mapView delegate methods.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if annotation is PinAnnotation {
let reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
}
else {
pinView?.annotation = annotation
}
return pinView
} else if annotation is CustomBusinessCallOut {
let reuseId = "Callout"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = CalloutAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.addSubview(UIImageView(image: UIImage(named: "car")))
}
else {
pinView?.annotation = annotation
}
return pinView
} else {
return nil
}
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard view.annotation is PinAnnotation else { return }
if let pinAnnotation = view.annotation as? PinAnnotation {
let calloutAnnotation = CustomBusinessCallOut(location: pinAnnotation.coordinate)
calloutAnnotation.title = pinAnnotation.title
pinAnnotation.calloutAnnotation = calloutAnnotation
mapView.addAnnotation(calloutAnnotation)
}
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
guard view.annotation is PinAnnotation else { return }
if let pinAnnotation = view.annotation as? PinAnnotation,
let calloutAnnotation = pinAnnotation.calloutAnnotation {
mapView.removeAnnotation(calloutAnnotation)
pinAnnotation.calloutAnnotation = nil
}
}
I have a map and on this map I have custom annotation pins. All pins have same custom image. When i click on a pin, i need to change this annotation's image. I was using Google Maps before:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if marker.userData as? Int != nil {
let marker_tag = marker.userData as! Int
Datas.selectedMarkerIndex = marker_tag
if let selectedMarker = mapView.selectedMarker {
selectedMarker.icon = UIImage(named: "marker_gray")
}
mapView.selectedMarker = marker
marker.icon = UIImage(named: "marker_red")
}
return true
}
This was working fine. But I dont know how to do it with MapKit. I want to change just selected marker(pin) image. How can I do this?
Also I tried this but not working
How to change non selected annotation pin images on mapkit with Swift
And this is my code:
class CustomPointAnnotation: MKPointAnnotation {
var pinImageName:String!
var userData:Int!
}
extension MyView: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "my_pin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
} else {
annotationView?.annotation = annotation
}
let customPointAnnotation = annotation as! CustomPointAnnotation
annotationView?.isDraggable = false
annotationView?.canShowCallout = false
annotationView?.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
annotationView?.image = UIImage(named: customPointAnnotation.pinImageName)
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let anno = view.annotation as? CustomPointAnnotation {
let marker_tag = anno.userData!
print(marker_tag)
}
}
func addMarkersOnMap(){
if Datas.myArray.count != 0 {
Datas.selectedMarkerIndex = 0
for i in 0..<Datas.myArray.count{
let lat = Datas.myArray[i].lat
let lng = Datas.myArray[i].lng
myArray.append(CustomPointAnnotation())
if lat != nil {
let location = CLLocationCoordinate2D(latitude: lat!, longitude: lng!)
myArray[i].pinImageName = "marker_gray"
myArray[i].coordinate = location
myArray[i].userData = i
pinAnnotationView = MKPinAnnotationView(annotation: myArray[i], reuseIdentifier: "my_pin")
mapView.addAnnotation(pinAnnotationView.annotation!)
}
}
"selected" means "tapped"? If so, Try the following code:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
view.image = UIImage(named: "marker_gray")
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
view.image = UIImage(named: "marker_red")
}
How tap or clickable annotation title in Map. For example I have code:
#IBOutlet var Map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
Map.delegate = self
let location = CLLocationCoordinate2DMake(lat!, lon!)
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegion(center: location, span: span)
Map.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = "Title"
Map.addAnnotation(annotation)
}
I try use UITapGestureRecognizer and mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) but it doesn't work. Maybe someone have any ideas
Implement the delegate methods.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
print(#function)
if control == view.rightCalloutAccessoryView {
// Do something
}
}
I've tried to add title and subtitle to my annotations, but all my attempts had failed. Please help me!
import UIKit
import MapKit
class MyPointAnnotation : MKPointAnnotation{
var pinTintColor: UIColor?
}
class MapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self;
let hello = MyPointAnnotation()
hello.coordinate = CLLocationCoordinate2D(latitude: 46.771210, longitude: 23.623635)
hello.title = "tile"
hello.subtitle = "subtitle"
hello.pinTintColor = .blue
let hellox = MyPointAnnotation()
hellox.coordinate = CLLocationCoordinate2D(latitude: 44.426767, longitude: 26.102538)
hellox.pinTintColor = .blue
mapView.addAnnotation(hello)
mapView.addAnnotation(hellox)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
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")
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
if #available(iOS 9.0, *) {
annotationView?.pinTintColor = annotation.pinTintColor
} else {
// Fallback on earlier versions
}
}
return annotationView
}
}
My problem solved with below code.In swift 4
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
let location = CLLocationCoordinate2D(latitude: 12.956360, longitude: 77.716615)
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: 12.956360, longitude: 77.716615)
map.setRegion(MKCoordinateRegionMakeWithDistance(location, 1500, 1500), animated: true)
annotation.title = "your title"
annotation.subtitle = "your subtitle"
map.addAnnotation(annotation);
}
You need set canShowCallout true to show title and subtitle.
Try the following code.
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 let annotation = annotation as? MyPointAnnotation {
if #available(iOS 9.0, *) {
annotationView?.pinTintColor = annotation.pinTintColor
} else {
// Fallback on earlier versions
}
}
return annotationView
}
I have 2 pins in mapkit, both are under the same annotation view so it makes since that both of the pins are the same color. How can I make the pins different colors. I would like hello to be red and hellox to be blue.
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet var jmap: MKMapView!
override func viewDidLoad() {
jmap.delegate = self;
let hello = MKPointAnnotation()
hello.coordinate = CLLocationCoordinate2D(latitude: 40, longitude: -73)
jmap.addAnnotation(hello)
let hellox = MKPointAnnotation()
hellox.coordinate = CLLocationCoordinate2D(latitude: 34, longitude: -72)
jmap.addAnnotation(hellox)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKPinAnnotationView()
annotationView.pinTintColor = .blue
return annotationView
}}
Subclass MKPointAnnotation to add any custom property that you want, such as a pinTintColor:
class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?
}
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet var jmap: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
jmap.delegate = self
let hello = MyPointAnnotation()
hello.coordinate = CLLocationCoordinate2D(latitude: 40, longitude: -73)
hello.pinTintColor = .red
let hellox = MyPointAnnotation()
hellox.coordinate = CLLocationCoordinate2D(latitude: 34, longitude: -72)
hellox.pinTintColor = .blue
jmap.addAnnotation(hello)
jmap.addAnnotation(hellox)
}
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")
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
annotationView?.pinTintColor = annotation.pinTintColor
}
return annotationView
}
}