Cannot change pins for images in a map - ios

I have a map where I mark points based on Parse data. This works correctly. When I try to change the red pins of the map with a custom image, it seems that everything is OK but when I run the app in the simulator, the red pins are there and my image doesn't appear. I have tried some similar versions of the code I have with the same result. I tried to print the annotationView in the console and seems that have the image saved the line before the return. Where is the error? What I have to do to show the custom image correctly? Thanks.
import UIKit
import MapKit
import CoreLocation
import Foundation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
var MapViewLocationManager:CLLocationManager! = CLLocationManager()
var currentLoc: PFGeoPoint! = PFGeoPoint()
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
override func viewDidAppear(animated: Bool) {
let annotationQuery = PFQuery(className: "_User")
currentLoc = PFGeoPoint(location: MapViewLocationManager.location)
annotationQuery.whereKey("restaurant", equalTo: true)
annotationQuery.whereKey("restaurantPosition", nearGeoPoint: currentLoc, withinMiles: 6000)
annotationQuery.findObjectsInBackgroundWithBlock {
(posts, error) -> Void in
if error == nil {
// The find succeeded.
print("Successful query for annotations")
let myPosts = posts as [PFObject]!
for post in myPosts {
let point = post["restaurantPosition"] as! PFGeoPoint
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude)
self.mapViewN(self.mapView, viewForAnnotation: annotation).annotation = annotation
self.mapView.addAnnotation(annotation)
}
} else {
// Log details of the failure
print("Error: \(error)")
}
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error: " + error.localizedDescription)
}
func mapViewN(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView {
let identifier = "pin"
// Reuse the annotation if possible
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
annotationView!.image = UIImage(named: "map_marker_2")
}
else {
annotationView!.annotation = annotation
}
print(annotationView?.image)
return annotationView!
}
}

Your method map view:viewForAnnotation: is misnamed. You have
func mapViewN(mapView: MKMapView,
viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView
That N in the name does not belong there, so your delegate method will never be called.
(The method name for a delegate method must be exactly correct or the method doesn't get called. For a required delegate method you may even crash.)
It should be:
func mapView(mapView: MKMapView,
viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView

mapViewN:viewForAnnotation delegate is called?
Maybe you should rename mapViewN to mapView.
func mapViewN(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView {
->
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {

Related

MKLocalSearch (search.start)always goes in the error flow. (SWIFT)

I've been trying to learn swift for the past few days and just started my own project! As part of the project I wanted to show nearby cocktail bars on a map, I was able to find some nice info online and have been able to show a map with my current location. I also found info on how to find nearby locations: https://developer.apple.com/documentation/mapkit/mklocalsearch/request
Unfortunately this last one never seems to work, it just goes out of the function and does not return any locations, could anyone help me further? Below is the code of my viewcontroller with the function getNearbyLandmarks which doesn't work as intended.
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet var mapView: MKMapView!
let manager = CLLocationManager()
private var landmarks: [Landmark] = [Landmark]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
manager.stopUpdatingLocation()
render(location)
}
}
func render(_ location: CLLocation){
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude,
longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.01,
longitudeDelta: 0.01)
let region = MKCoordinateRegion(center: coordinate,
span: span)
mapView.delegate = self
mapView.setRegion(region,
animated: true)
let pin = MKPointAnnotation()
pin.coordinate = coordinate
pin.title = "Current location"
mapView.addAnnotation(pin)
self.getNearByLandmarks()
updateAnnotations(from: mapView)
}
func mapView(_ mapViewIcon: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapViewIcon.dequeueReusableAnnotationView(withIdentifier: "custom")
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation,
reuseIdentifier: "custom")
annotationView?.canShowCallout = true
}else{
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "User")
return annotationView
}
private func getNearByLandmarks(){
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = "coffee"
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.start{(response, error) in
if let response = response {
let mapItems = response.mapItems
self.landmarks = mapItems.map{
Landmark(placemark: $0.placemark)
}
}
}
}
private func updateAnnotations(from mapView: MKMapView){
let annotations = self.landmarks.map(LandmarkAnnotation.init)
mapView.addAnnotations(annotations)
}
}
You call getNearByLandmarks, and then immediately try to update the annotations:
self.getNearByLandmarks()
updateAnnotations(from: mapView)
but getNearByLandmarks is asynchronous, and takes some time to complete. You need to update the annotations whenever private var landmarks changes, one way is to update it in all the places that set that, like where you say
self.landmarks = mapItems.map{
Landmark(placemark: $0.placemark)
}
note you don't call updateAnnotations(from: mapView) there.
Or you could add a didSet property observer to landmarks itself so that updateAnnotations is called whenever it changes.

Swift MapKit - Annotations dont show in the MapView

I am trying to create a MapView using MapKit framework which looks for the current user location and displays restaurants nearby. However, when I am trying to show annotations then they don't show up.
I have tried printing (response.mapItems) to check if it works and the result is good because it prints information about some restaurants that were found in the console.
Therefore, I don't know why these are not annotated on the map.
Here is the code that I've made:
import UIKit
import MapKit
import CoreLocation
class RestaurantViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.025, 0.025)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
map.setRegion(region, animated: true)
self.map.showsUserLocation = true
}
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "restaurant"
request.region = map.region
let search = MKLocalSearch(request: request)
search.start { (response, error) in
guard let response = response else {
return
}
for item in response.mapItems {
print(response.mapItems) - Console shows some restaunrant outputs that were correctly fetched
let annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
DispatchQueue.main.async {
self.map.addAnnotation(annotation)
}
}
}
}
}
You annotation implementation is a little off, allow me to explain how it should be.
Adding annotations to your map relies on two things.
A class conforming to MKAnnotation.
A subclass of MKAnnotationView.
Your map has annotations added to it but it does not know how to show them, so it shows nothing. You can tell it how to show them by implementing viewForAnimation. Take a look at my example below:
class PinAnnotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
super.init()
}
}
class PinAnnotationView: MKAnnotationView {
#available(*, unavailable)
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(annotation: PinAnnotation) {
super.init(annotation: annotation, reuseIdentifier: nil)
self.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
self.image = UIImage(named: "mypinimage") // or whatever.
}
}
Here we have the definition for the two objects I spoke of above.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let imageAnnotation = annotation as? ImageAnnotation {
let view = ImageAnnotationView(annotation: imageAnnotation)
return view
}
return nil
}
Here we have the implementation of viewForAnnotation that I spoke of above.
Implement viewForAnnotation
func mapView(_ mapView: MKMapView,viewFor annotation: MKAnnotation) -> MKAnnotationView?
see my demo here customPinAnnotationButton

How to change MapKit's pin color in Swift 3/4?

So, I am creating an app with MapKit. So, I need some help of changing the maps pin color from red to any color possible. I tried every way, I can't just not find a solution. Can any one check my code, and help me apply it to my code below of changing the map's pin tintColor. Thanks in advance.
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
}
extension ViewController: CLLocationManagerDelegate {
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.014, longitudeDelta: 0.014)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.region = region
let location = CLLocation(latitude: latitude, longitude: longitude)
let place = Place(location: location, reference: reference, name: name, address: address)
self.places.append(place)
let annotation = MyHome(location: place.location!.coordinate, title: place.placeName)
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
}
}
}
}
}
}
}
MyHome CLass
import Foundation
import MapKit
class MyHome: NSObject, MKAnnotation {
let coordinate: CLLocationCoordinate2D
let title: String?
init(location: CLLocationCoordinate2D, title: String) {
self.coordinate = location
self.title = title
super.init()
}
}
MapView
fileprivate var locationManager = CLLocationManager()
fileprivate var heading: Double = 0
fileprivate var interactionInProgress = false
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
{
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required public init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
open override func viewDidLoad()
{
super.viewDidLoad()
self.mapView.isRotateEnabled = false
if let annotations = self.annotations
{
addAnnotationsOnMap(annotations)
}
locationManager.delegate = self
}
open override func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear(animated)
locationManager.startUpdatingHeading()
}
open override func viewDidDisappear(_ animated: Bool)
{
super.viewDidDisappear(animated)
locationManager.stopUpdatingHeading()
}
open func addAnnotations(_ annotations: [ARAnnotation])
{
self.annotations = annotations
if self.isViewLoaded
{
addAnnotationsOnMap(annotations)
}
}
fileprivate func addAnnotationsOnMap(_ annotations: [ARAnnotation])
{
var mapAnnotations: [MKPointAnnotation] = []
for annotation in annotations
{
if let coordinate = annotation.location?.coordinate
{
let mapAnnotation = MKPointAnnotation()
mapAnnotation.coordinate = coordinate
let text = String(format: "%#, AZ: %.0f, VL: %i, %.0fm", annotation.title != nil ? annotation.title! : "", annotation.azimuth, annotation.verticalLevel, annotation.distanceFromUser)
mapAnnotation.title = text
mapAnnotations.append(mapAnnotation)
}
}
mapView.addAnnotations(mapAnnotations)
mapView.showAnnotations(mapAnnotations, animated: false)
}
open func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
{
heading = newHeading.trueHeading
if(!self.interactionInProgress && CLLocationCoordinate2DIsValid(mapView.centerCoordinate))
{
let camera = mapView.camera.copy() as! MKMapCamera
camera.heading = CLLocationDirection(heading);
self.mapView.setCamera(camera, animated: false)
}
}
open func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool)
{
self.interactionInProgress = true
}
open func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool)
{
self.interactionInProgress = false
}
}
you have to change its color in MKMapViewDelegate delegate method
#IBOutlet weak var customMap: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let anoot = MKPointAnnotation()
anoot.coordinate = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
customMap.addAnnotation(anoot)
customMap.delegate = self
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
annotationView.pinTintColor = UIColor.green
return annotationView
}
you can do it in your code like this
class ViewController: UIViewController {
var locationManager = CLLocationManager()
#IBOutlet weak var yourMap: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
yourMap.delegate = self
let anoot = MKPointAnnotation()
anoot.coordinate = CLLocationCoordinate2D.init(latitude: 23.0225, longitude: 72.5714)
yourMap.addAnnotation(anoot)
yourMap.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
}
}
extension ViewController: CLLocationManagerDelegate, MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
annotationView.pinTintColor = UIColor.green
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.014, longitudeDelta: 0.014)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
yourMap.region = region
// let location = CLLocation(latitude: latitude, longitude: longitude)
// let place = Place(location: location, reference: reference, name: name, address: address)
// self.places.append(place)
//
// let annotation = MyHome(location: place.location!.coordinate, title: place.placeName)
//
// DispatchQueue.main.async {
//
// self.mapView.addAnnotation(annotation)
// }
}
}
}
}

Swift : MKAnnotation, implementation of mapView delegate to customize pin

I'm just trying to convert the red pins into purple ones.
Here is the FirstViewController.swift code :
import UIKit
import CoreLocation
import MapKit
class FirstViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var theMap: MKMapView!
var locationManager = CLLocationManager()
var userLocation = CLLocation()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
//The Pin
let pin1 = CLLocationCoordinate2D(
latitude: 48.89,
longitude: 2.6968
)
let thepoint = MKPointAnnotation()
thepoint.coordinate = pin1
thepoint.title = "the title"
thepoint.subtitle = "the subtitle"
theMap.addAnnotation(thepoint)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Purple
}
else {
pinView!.annotation = annotation
}
return pinView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("error")
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
userLocation = locations[0] as! CLLocation
locationManager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
theMap.setRegion(region, animated: false)
}
}
I know that I'm doing wrong with the implementation of the mapView function.
Is there anyone to help me ?
Thanks

Adding accessory button on user location callout

I'm making a clickable placemark. I set the title of the placemark. Title is adress. I want If you click on that adress It will push to another View to Show Adress Number,City,Country etc. I Tried this code. But It haven't UIButton in application in placemark, why?
EDIT: If I put breakpoint to func calloutAccessoryControlTapped it isn't crashing.
func mapView(Mapa: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
var pin = "pin"
var view = Mapa.dequeueReusableAnnotationViewWithIdentifier(pin) as? MKPinAnnotationView
if view == nil {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: pin)
view!.canShowCallout = true
view!.animatesDrop = true
var arrowButton = UIButton()
view!.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIButton
} else {
view!.annotation = annotation
}
return view
}
func mapView(Mapa: MKMapView!, annotation: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotation.rightCalloutAccessoryView {
println("Pressed!")
}
}
Whole code:
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var Mapa: MKMapView!
let locationManager = CLLocationManager()
var detail: UIButton!
override func viewDidLoad()
{
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
Mapa.delegate = self
Mapa.mapType = MKMapType.Standard
Mapa.showsUserLocation = true
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
//--- Find Address of Current Location ---//
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
{
//--- CLGeocode to get address of current location ---//
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in
let spanX = 0.007
let spanY = 0.007
var newRegion = MKCoordinateRegion(center: self.Mapa.userLocation.coordinate, span: MKCoordinateSpanMake(spanX, spanY))
self.Mapa.setRegion(newRegion, animated: true)
if (error != nil)
{
println("Reverse geocoder failed with error" + error.localizedDescription)
return
}
if placemarks.count > 0
{
let pm = placemarks[0] as! CLPlacemark
self.displayLocationInfo(pm)
}
else
{
println("Problem with the data received from geocoder")
}
})
}
func displayLocationInfo(placemark: CLPlacemark?)
{
if let Placemark = placemark
{
//Stop updating kvôli vydrži baterke
locationManager.stopUpdatingLocation()
let location = self.locationManager.location
var latitude: Double = location.coordinate.latitude
var longitude: Double = location.coordinate.longitude
let adresa = (Placemark.thoroughfare != nil) ? Placemark.thoroughfare : "Ulica: "
let cislo = (Placemark.subThoroughfare != nil) ? Placemark.subThoroughfare : "Číslo ulice:"
let mesto = (Placemark.locality != nil) ? Placemark.locality : "Mesto: "
let stat = (Placemark.country != nil) ? Placemark.country : "Štát: "
var coordinates:CLLocationCoordinate2D = placemark!.location.coordinate
let theLocation: MKUserLocation = Mapa.userLocation
theLocation.title = adresa
println("GPS Súradnice :: \(latitude), \(longitude)")
println(mesto)
println(adresa)
println(cislo)
println(stat)
}
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
println("Chyba pri aktualizovaní lokácie " + error.localizedDescription)
}
func mapView(Mapa: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
var pin = "pin"
var view = Mapa.dequeueReusableAnnotationViewWithIdentifier(pin) as? MKPinAnnotationView
if view == nil {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: pin)
view!.canShowCallout = true
view!.animatesDrop = true
var arrowButton = UIButton()
view!.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIButton
} else {
view!.annotation = annotation
}
return view
}
func mapView(Mapa: MKMapView!, annotation: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotation.rightCalloutAccessoryView {
println("Pressed!")
}
}
}
You want to put an accessory button on the callout of the blue dot (user location).
In the viewForAnnotation delegate method, you do have code that creates an annotation view and sets the rightCalloutAccessoryView but at the top of the method there is this code:
func mapView(Mapa: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
The map's user location annotation is of type MKUserLocation so when the map view calls viewForAnnotation for it, this code returns nil for it which the map view interprets as "display the default view and callout for this annotation". The default callout only shows a title and subtitle.
The code that creates a custom view and sets rightCalloutAccessoryView never executes.
To set a rightCalloutAccessoryView, you need a reference to the actual annotation view object.
You could remove that return nil for the MKUserLocation but then you'll get a standard pin instead of an animated blue dot.
You can't create your own instance of the animated blue dot view because that class is private.
So you can't create or get access to the user location annotation view in the viewForAnnotation delegate method.
A place where you can reliably get access to the actual user location annotation view is in the didAddAnnotationViews delegate method. I suggest this method because it means an annotation view has actually been created and is on the screen.
In this method, call the map view's viewForAnnotation instance method and pass it its userLocation annotation and then set the view's rightCalloutAccessoryView:
func mapView(mapView: MKMapView!, didAddAnnotationViews views: [AnyObject]!) {
if let ulav = mapView.viewForAnnotation(mapView.userLocation) {
ulav.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIButton
}
}
Unrelated to the callout button not appearing but:
Your calloutAccessoryControlTapped delegate method is named wrong and will not get called when the button is tapped.
Your method is named mapView(annotation:calloutAccessoryControlTapped).
The annotation parameter must be named annotationView and even though naming the map view parameter Mapa will work, I suggest sticking to the signature given in the documentation so the revised method would be:
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if control == annotationView.rightCalloutAccessoryView {
println("Pressed!")
}
}

Resources