SteBra SteBra - 9 months ago 29
Swift Question

How to go through mapView.annotations array with objects of different type?

I have several different custom Annotation objects.
They all extend MKAnnotation class and it's protocol.

This is how at least two of them look like, there are several more of them, and frankly, they all look very similar:

My BaseAnnotation protocol:

import MapKit
/// Defines the shared stuff for map annotations
protocol BaseAnnotation: MKAnnotation {
var imageName: String { get }
var coordinate: CLLocationCoordinate2D { get set }
}


Quest Giver Annotation:

import UIKit
import MapKit

class QuestGiverAnnotation: NSObject, BaseAnnotation {
var imageName = "icon_quest"
var questPin: QuestPin?

@objc var coordinate: CLLocationCoordinate2D


// MARK: - Init

init(forQuestItem item: QuestPin) {
self.questPin = item

if let lat = item.latitude,
lng = item.longitude {
self.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lng)
} else {
self.coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
}
}

init(location: CLLocationCoordinate2D) {
self.coordinate = location
}
}


Resource Annotation:

import UIKit
import MapKit

class ResourceAnnotation: NSObject, BaseAnnotation {
var imageName: String {
get {
if let resource = resourcePin {
return resource.imageName
} else {
return "icon_wood.png"
}
}
}
var resourcePin: ResourcePin?
@objc var coordinate: CLLocationCoordinate2D
var title: String? {
get {
return "Out of range"
}
}


// MARK: - Init

init(forResource resource: ResourcePin) {
self.resourcePin = resource

if let lat = resource.latitude,
lng = resource.longitude {
self.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lng)
} else {
self.coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
}
}

init(location: CLLocationCoordinate2D) {
self.coordinate = location
}
}


As I said, there are 2-3 more, but they are more or less same as these two.
Don't ask me why I made them like this...I needed them to be like this.

Ok, problem occurs when I want to list all added map annotations through
mapView.annotations
.

I get
fatal error: NSArray element failed to match the Swift Array Element type


And I understand that it's because
annotations
array consists of Objects of diferent type, but i am having dificulties getting an object of a certain type.

This is one of the ways I tried to get an annotation I need from the array, ut I have failed:

func annotationExistsAtCoordinates(lat: Double, long:Double) -> Bool{
var annotationExists = false
**let mapAnnotations: [Any] = self.annotations**
for item in mapAnnotations{
if let annotation = item as? QuestGiverAnnotation{
if annotation.coordinate.latitude == lat && annotation.coordinate.longitude == long{
annotationExists = true
}
//let annotation = self.annotations[i] as! AnyObject
}
}

return annotationExists
}


I get error on this line:
let mapAnnotations: [Any] = self.annotations


So, my question is: how to get objects of different type from one array without getting a
fatal error: NSArray element failed to match the Swift Array Element type
?

Answer Source

Initializing with array of MKAnnotation still throws error.

do:

let mapAnnotations: [AnyObject] = self.annotations

This worked.