Find index of annotation MapKit
I think the main problem here is that you expect that mapView.annotations
returns an array with all annotations being in the same order as your detailsDict
-Array. I think that this assumption is error prone, because it would highly depend on the internal implementation of the MapKit framework.
A better way would be storing the Dictionary entry together with the PlaceAnnotation
that you add to the map:
- Add a new property
details
to classPlaceAnnotation
- Set
details
value when you create thePlaceAnnotation
- in
calloutAccessoryControlTapped
, get back the details property from the PlaceAnnotation - transfer this value to detail controller (maybe via your
selectedPlace
property, but I would prefer in instatiating the ViewController directly and setting the value).
Get the array index from annotation
I assume ShopLocation
already conforms to MKAnnotation
, if not then make it conform and pass it to MKAnnotationView
's initializer. This will make it available in the delegate
method, via view.annotation
Now that you have access to the ShopLocation
instance, there are two solutions that come to my mind for finding it's index in the shop
Conform to
Equatable
- this will enable thefirstIndex(of:)
method ofArray
(actually ofCollection
to whichArray
conforms)extension ShopLocation: Equatable {
static func ==(lhs: ShopLocation, rhs: ShopLocation) -> Bool {
// place here the conditions for two instances to be equal
}
// ... later in the code
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let shopLocation = view.annotation as? ShopLocation else {
// this early returns if the annotation is not a shop location,
// if you don't wan't that you can use an if-let instead
return
}
let index = LocationList().shop.firstIndex(of: shopLocation)
// do what you need with the index
}Use the
firstIndex(where:)
method ofArray
(again, actually ofCollection
:)func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let shopLocation = view.annotation as? ShopLocation else {
// this early returns if the annotation is not a shop location,
// if you don't wan't that you can use an if-let instead
return
}
let index = LocationList().shop.firstIndex(where: { shopLocation in
return // same conditions as for the Equatable
})
// do what you need with the index
}
Personally, I'd recommend approach #1, even Apple recommends conforming value types to Equatable. Conforming to Equatable
helps with code reduction, and enables lots of other functions besides the index(of:)
mentioned here.
How to get Annotation index in Mapkit?
use this
NSUInteger index = [mapView.annotations indexOfObject:view.annotation];
NSLog(@"index no %d",index);
you get the index
NSInteger i = 0;
for (NSDictionary *row in locations) {
NSNumber *latitude = [row objectForKey:@"latitude"];
NSNumber *longitude = [row objectForKey:@"longitude"];
NSString *title = [row objectForKey:@"title"];
NSString * image=[row objectForKey:@"image"];
imageDic =[row objectForKey:image];
[customTickLocations addObject:[row objectForKey:@"image"]];
//Create coordinates from the latitude and longitude values
CLLocationCoordinate2D coord;
coord.latitude = latitude.doubleValue;
coord.longitude = longitude.doubleValue;
MapViewAnnotation * annotation =[[MapViewAnnotation alloc] initWithTitle:image initWithSubTitle:title AndCoordinate:coord Withindex:i];
i++;
[annotations addObject:annotation];
}
plz add one more property in MapViewAnnotation for index then try.
Find selected MapKit Annotation's postID
Try the following code:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let annotation = view.annotation as? EventAnnotation {
mapEventID = annotation.eventKey
}
}
Get indexPath of mapView annotation
MKAnnotationView * view = ...
NSUInteger index = [mapView.annotations indexOfObject:view.annotation];
How to access specific index of MKAnnotation
MKMapViewDelegate provides a delegate method mapView:annotationView:calloutAccessoryControlTapped: Implementing this method provides you with the MKAnnotationView of the MKAnnotation instance you're looking for. You can call the MKAnnotationView's annotation property to get the corresponding instance of the MKAnnotation.
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
var sortedAnnotationArray: [MKAnnotation] = [] //create your array of annotations.
//your ViewDidAppear now looks like:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
for (var i = 0; i < latArray.count; i++) {
let individualAnnotation = Annotations(title: addressArray[i], coordinate: CLLocationCoordinate2D(latitude: latArray[i], longitude: longArray[i]))
mapView.addAnnotation(individualAnnotation)
//append the newly added annotation to the array
sortedAnnotationArray.append(individualAnnotation)
}
}
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
let theAnnotation = view.annotation
for (index, value) in enumerate(sortedAnnotationArray) {
if value === theAnnotation {
println("The annotation's array index is \(index)")
}
}
}
}
How can I detect which annotation was selected in MapView
For that you can use selected Annotation
from didSelectAnnotationView
, then store that annotation to instance variable and after that used annotation in your Button
action method.
var selectedAnnotation: MKPointAnnotation?
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
self.selectedAnnotation = view.annotation as? MKPointAnnotation
}
func info(sender: UIButton) {
print(selectedAnnotation?.coordinate)
}
Edit: As of you have custom MKAnnotation
class you need to use that.
var selectedAnnotation: Islands?
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
self.selectedAnnotation = view.annotation as? Islands
}
Z-index of iOS MapKit user location annotation
Update for iOS 14
I know it's an old post, but the question is still applicable and you end up here when typing it into your favorite search engine.
Starting with iOS 14, Apple introduced a zPriority
property to MKAnnotationView
. You can use it to set up the z-index for your annotations using predefined constants or floats.
Also, Apple made it possible to finally create the view for the user location on our own and provided MKUserLocationView
as a subclass of MKAnnotationView
.
From the documentation for MKUserLocationView
:
If you want to specify additional configuration, such as
zPriority
,
create this annotation view directly. To display the annotation view,
return the instance frommapView(_:viewFor:)
.
The following code snippet shows how this can be done (add the code to your MKMapViewDelegate
):
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Alter the MKUserLocationView (iOS 14+)
if #available(iOS 14.0, *), annotation is MKUserLocation {
// Try to reuse the existing view that we create below
let reuseIdentifier = "userLocation"
if let existingView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) {
return existingView
}
let view = MKUserLocationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
view.zPriority = .max // Show user location above other annotations
view.isEnabled = false // Ignore touch events and do not show callout
return view
}
// Create views for other annotations or return nil to use the default representation
return nil
}
Note that per default, the user location annotation shows a callout when tapping on it. Now that the user location overlays your other annotations, you'd probably want to disable this, which is done in the code by setting .isEnabled
to false
.
Get Index of MKAnnotation in MapView.annotations Array
The recommended way of handling this is to make your own class that implements the MKAnnotation protocol and has a property that you can check during viewForAnnotations
to see what colour to use. The annotations
array from MKMapView is not guaranteed to be in the order in which you add annotations to the map. You may add annoy, annoy and then annoy but you may get back [anno2, anno3, anno1]. That's just the way it is and you can't change that. So, you could keep your own array of annotations that won't get rearranged. Or use the extra property idea if that will suit.
One thing you should not do is add more annotations during the viewForAnnotation
function, that's really messed up.
Related Topics
Swift Nstimer Dynamically Changing Interval
Swift Displaying The Time or Date Based on Timestamp
Adding Data to a Specific UId in Firebase
Avoid Equatable and Hashable Boilerplate, Swift 4.2
Protocol Extension Doesn't Work with Rct_Export_View_Property
Back to Table View from Detail Page Without Reload, Swift
Swiching Between 2 Diferent Nsviewcontrollers with Data
Updating Existing Constraints Does Not Work, Wrong Use of .Active Property
Swift-Animate Cashapelayer Stroke Color
Swift: Draw a Semi-Sphere in Mkmapview
Automatic Select a Date in Datepicker in Swift Language
Nsnumber/Nsdecimalnumber Bizarre Behavior
How to Resolve Rctpromiseresolveblock After Bftask
Allow Line Editing When Reading Input from The Command Line
How to Populate Table Rows, Using a [String] Array Sent from iPhone by Watch Connectivity
Swift Nsbundle Pathforresource() Returns Nil
Nstimer Scheduledtimerwithtimeinterval and Target Is "Class Level Function"