How to add two or more buttons to annotationView: MKAnnotationView?
I have done it
From documentation left and right calloutAccessoryView are low width and height. So, we can add buttons and image only in detailCalloutAccessoryView.
Here is my code. It's working. I haven't done a review. Because it's more clear for understanding.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if !(view.annotation! is MKUserLocation) {
let customPin = view.annotation as! CustomPin
self.spotDetailsForSendToPostsStripController = customPin.spotDetailsItem // its for sending to another controller.
configureDetailView(annotationView: view, spotPin: customPin.spotDetailsItem)
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if !(annotation is CustomPin) {
return nil
}
let identifier = "CustomPin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
return annotationView
}
func configureDetailView(annotationView: MKAnnotationView, spotPin: SpotDetailsItem) {
let width = 250
let height = 250
let snapshotView = UIView()
let views = ["snapshotView": snapshotView]
snapshotView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[snapshotView(250)]", options: [], metrics: nil, views: views))
snapshotView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[snapshotView(250)]", options: [], metrics: nil, views: views))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height - 40))
// configure button1
let button1 = UIButton(frame: CGRect(x: 0, y: height - 35, width: width / 2 - 5, height: 35))
button1.setTitle("Info", for: .normal)
button1.backgroundColor = UIColor.darkGray
button1.layer.cornerRadius = 5
button1.layer.borderWidth = 1
button1.layer.borderColor = UIColor.black.cgColor
button1.addTarget(self, action: #selector(MainFormController.goToInfo), for: .touchDown)
// configure button2
let button2 = UIButton(frame: CGRect(x: width / 2 + 5, y: height - 35, width: width / 2, height: 35))
button2.setTitle("Posts", for: .normal)
button2.backgroundColor = UIColor.darkGray
button2.layer.cornerRadius = 5
button2.layer.borderWidth = 1
button2.layer.borderColor = UIColor.black.cgColor
button2.addTarget(self, action: #selector(MainFormController.goToPosts), for: .touchDown)
// configure image
let image = UIImage(contentsOfFile: "plus-512.gif")
imageView.image = image // implement your own logic
imageView.layer.cornerRadius = imageView.frame.size.height / 10
imageView.layer.masksToBounds = true
imageView.layer.borderWidth = 0
imageView.contentMode = UIViewContentMode.scaleAspectFill
// adding it to view
snapshotView.addSubview(imageView)
snapshotView.addSubview(button1)
snapshotView.addSubview(button2)
annotationView.detailCalloutAccessoryView = snapshotView
}
func goToPosts() {
print("go to posts") // your implementation(segues and etc)
}
func goToInfo() {
print("go to info") // your implementation(segues and etc)
}
CustomPin:
class CustomPin: MKPointAnnotation {
var spotDetailsItem: SpotDetailsItem! // its my info of this place
}
Works like a charm
How to add different button action to the second annotation /pin in map view using swift2
The simplest way to know on which annotation you tap is using creating custom annotation class and adding annotation of it. So create one annotation class MyAnnotation
child class of MKPointAnnotation
and maintain one uniqueId with your multiple annotation.
class MyAnnotation: MKPointAnnotation {
var uniqueId: Int!
}
Now you need to add annotation of type MyAnnotation
instead of MKPointAnnotation
.
let annotation = MyAnnotation()
annotation.coordinate = locations
annotation.title = "Zaid Homes"
annotation.subtitle = "Hay aljameaa"
//Set uniqueId for annotation
annotation.uniqueId = 1
map.addAnnotation(annotation)
let annotation2 = MyAnnotation()
annotation2.coordinate = location2
annotation2.title = "Zaid "
annotation2.subtitle = "aljameaa"
//Set uniqueId for annotation
annotation2.uniqueId = 2
map.addAnnotation(annotation2)
Now check this uniqueId
in calloutAccessoryControlTapped
method on which annotation you tapped.
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if (control as? UIButton)?.buttonType == UIButtonType.detailDisclosure {
mapView.deselectAnnotation(view.annotation, animated: false)
if let myAnnotation = view.annotation as? MyAnnotation {
if (myAnnotation.uniqueId == 1) {
performSegue(withIdentifier: "info1", sender: view)
}
else {
performSegue(withIdentifier: "info2", sender: view)
}
}
}
}
How to add a button to an annotation, current solution not working
You need to add the delegate MKMapViewDelegate
. And use the function,
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
}
How to add a button to the MKPointAnnotation?
You are doing it right.You just need to have these methods implemented for adding button along with title and subtitle
iOS 8 and Xcode 6
import UIKit
import MapKit
import CoreLocation
class MapKitViewController: UIViewController, MKMapViewDelegate
{
let locationManager = CLLocationManager()
@IBOutlet weak var nmapView: MKMapView!
override func viewDidLoad()
{
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
let location = CLLocationCoordinate2D(
latitude: 53.4265107,
longitude: 14.5520357)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
nmapView.setRegion(region, animated: true)
nmapView.showsPointsOfInterest = false
nmapView.showsUserLocation = true
displayMarkers()
}
// When user taps on the disclosure button you can perform a segue to navigate to another view controller
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if control == view.rightCalloutAccessoryView{
println(view.annotation.title) // annotation's title
println(view.annotation.subtitle) // annotation's subttitle
//Perform a segue here to navigate to another viewcontroller
// On tapping the disclosure button you will get here
}
}
// Here we add disclosure button inside annotation window
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("viewForannotation")
if annotation is MKUserLocation {
//return nil
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
//println("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}
var button = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton // button with info sign in it
pinView?.rightCalloutAccessoryView = button
return pinView
}
func displayMarkers() -> Void
{
let jsonURL: NSURL = NSURL(string: "http://atnight.wtznc.com/json.php")!
var dataFromNetwork: NSData = NSData(contentsOfURL: jsonURL)!
let json = JSON(data: dataFromNetwork)
var jsonSize = json.count
var todaysDate:NSDate = NSDate()
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var formattedDate:String = dateFormatter.stringFromDate(todaysDate)
let annotationView = MKAnnotationView()
// Adding button here wont do anything so remove these two lines
let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
annotationView.rightCalloutAccessoryView = detailButton
// For adding button we have to use a method named as viewForAnnotation
for(var i = 0; i < jsonSize; i++)
{
if(json[i]["rozpoczecie"].stringValue == formattedDate)
{
let clubID = json[i]["id_klub"].stringValue
let annotation = MKPointAnnotation()
let (resultSet, err) = SD.executeQuery("SELECT * FROM Clubs WHERE ID = ?", withArgs: [clubID])
if(err != nil){println("blad")}
else
{
for row in resultSet
{
let name = row["Name"]?.asString()
let latitude = row["Latitude"]?.asDouble()
let longitude = row["Longitude"]?.asDouble()
annotation.title = name
var markerLatitude: Double = latitude!
var markerLongitude: Double = longitude!
let location = CLLocationCoordinate2D(latitude: markerLatitude, longitude: markerLongitude)
annotation.setCoordinate(location)
annotation.subtitle = json[i]["nazwa"].stringValue
}
nmapView.addAnnotation(annotation)
}
}
}
}
}
Check out my output.
MKAnnotationView Swift Adding Info button
Am using Xcode 8.1 and Swift 3.0 . For Some reason Delegate methods are not firing until you set delegate in storyboard:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation {return nil}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
let calloutButton = UIButton(type: .DetailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}
return pinView
}
for button Action
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
print("button tapped")
}
}
I am attaching sample project for your issue
Map Sample Project Swift 3. 0 Xcode 8.1
Related Topics
Unrecognized Selector Sent to Instance Swift 3
How to Properly Handle a Nil Uiapplication.Sharedapplication().Keywindow
How to Draw a Simple Rounded Rect in Swift (Rounded Corners)
Passing Data Between View Controllers in Swift (From Tableview to Detailviewcontroller)
Sorting Struct Array in Swift 4
Calculate New Coordinates with Starting Position and Distance
Navigationlink Inside Lazyvgrid Cycles All Entries on Back, Swiftui
A Simple Code to Detect Any Beacon in Swift
How to Find the Index of a Tuple Element from an Tuple Array? iOS, Swift
Collectionview Flowlayout Overlapping When Scrolling Not Working
How to Fix Uilabel Text Spacing
Getting Uitableview Error "Unable to Dequeue a Cell with Identifier Cell"
Swift Bridging Header File Won't Work with Use_Frameworks
Change Selected Row Label Color in Picker View Swift 1.2