Making Mapbox annotations have different images depending on a variable? - swift

So I'm creating my annotations in a for loop as follows in the update map view function:
for item in array {
let latitude = item.latitude
let longitude = item.longitude
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let annotation = //make an annotation that uses a different image in Assets depending on a variable called "imageID"
mapView.addAnnotation(annotation)
}
I tried using reuseIdentifiers but wasn't even getting close to figuring this out. I also tried using the imageFor function and making a custom annotation class (to detect what the image passed in was and change the view accordingly) but it didn't work:
class CustomAnnotation: NSObject, MGLAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var image: UIImage?
init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
}
}
func mapView( _ mapView: MGLMapView, imageFor annotation: MGLAnnotation ) -> MGLAnnotationImage? {
let annotationImage: MGLAnnotationImage
let annotationImageToilet = mapView.dequeueReusableAnnotationImage(withIdentifier: "custom1")
let annotationImageDefault = mapView.dequeueReusableAnnotationImage(withIdentifier: "defaultImage")
switch annotation.image { //tried to sort according to the image value of the custom class
case "custom1":
var featureAnnotation = FeatureAnnotation(coordinate: annotation.coordinate, title: "Title", subtitle: "subtitle")
featureAnnotation.image = UIImage(named: "custom1")!
annotationImage = annotationImageToilet ?? featureAnnotation //couldn't get this line working properly
default:
var featureAnnotation = FeatureAnnotation(coordinate: annotation.coordinate, title: "Title", subtitle: "subtitle")
featureAnnotation.image = UIImage(named: "defaultImage")!
annotationImage = annotationImageDefault ?? featureAnnotation //couldn't get this line working properly
}
return annotationImage
}
Essentially, I just want the image of the custom annotations to change depending on what feature.imageID is, any help much appreciated!

Related

Drag Custom Annotation View

I have my CoreData custom Annotation class:
extension Annotation: MKAnnotation {
public var coordinate: CLLocationCoordinate2D {
let cllCoordinate = CLLocationCoordinate2D(latitude: self.latitude, longitude: self.longitude)
return cllCoordinate
}
public var title: String? {
return self.objectId
}
class func keyPathsForValuesAffectingCoordinate() -> Set<String> {
return Set<String>([ #keyPath(latitude), #keyPath(longitude) ])
}
#nonobjc public class func fetchRequest() -> NSFetchRequest<Annotation> {
return NSFetchRequest<Annotation>(entityName: "Annotation")
}
#NSManaged public var latitude: Double
#NSManaged public var longitude: Double
#NSManaged public var dateTime: Date
#NSManaged public var type: String
#NSManaged public var objectId: String?
}
combined with a fetchedResultsController adding and deleting annotations works fine. But now a want to drag an annotation to another position. But only with setting isDraggable to true is not all. I can’t find newer descriptions how this could be integrated.
Here my viewFor method:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard annotation is Annotation else { return nil }
let identifier = "Annotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.isDraggable = true
annotationView?.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
let customAnno = annotation as! Annotation
let image = UIImage(named: customAnno.type)
annotationView!.image = image
return annotationView
}
What else do i need? I want to press on the annotation, stay pressed and go to another position, then release the finger and the annotation stays there.
When it drags, it needs to change the coordinate of the underlying annotation. It can’t do that if it’s read-only. So, if you want to make it draggable, you must give the coordinate property a setter:
public var coordinate: CLLocationCoordinate2D {
get {
CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
set {
latitude = newValue.latitude
longitude = newValue.longitude
}
}

How do Views relate/loosely couple to Annotations? Annotationsarray I got, Views I need

SryImNew:
(lets say I want to Display gliphXYZ if title == "home")
"Annotation views are loosely coupled to a corresponding annotation object" https://developer.apple.com/documentation/mapkit/mkannotationview
How to couple them loosely, and where?
Or do I already have multiple MKAnnotationView automatically, if so how to address them & their properties?
My Case
I have running: An app that shows multiple pins for locations on a map
by
rawArrayWithFormat=[[namestring,lat,long][namestring,lat...]]
class Place: NSObject, MKAnnotation {
var title: String?
var subtitle: String?
var latitude: Double
var longitude:Double
var coordinate: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
Function that returns Array of [Place] by iterating through rawArray
func getMapAnnotations() -> [Place] {
var annotations:Array = [Place]()
for item in rawArray {
let lat = (item[1] as AnyObject) as! Double
let long = (item[2] as AnyObject) as! Double
let annotation = Place(latitude: lat, longitude: long)
annotation.title = (item[0] as AnyObject) as? String
annotations.append(annotation)
}
return annotations
And then in ViewController
#IBOutlet weak var mapView: MKMapView!
...
finally I call in override func viewDidLoad{
mapView.addAnnotations(getMapAnnotations())

Error "Missing argument for parameter 'coordinate' in call"

I have a custom MkAnnotation that has a title, subtitle, and extra information associated with it for use on an map view. I am passing this information to another UIViewController. However there seems to be some issue with my coordinate that I have allocated for the pin. The error is highlighted in the setting information of pin below on the line of code "var bridge17pin = MyAnnotation()".
override func viewDidLoad() {
super.viewDidLoad()
//for users location
myLocMgr.desiredAccuracy = kCLLocationAccuracyBest
myLocMgr.requestWhenInUseAuthorization()
myLocMgr.startUpdatingLocation()
myLocMgr.delegate = self
mapView.delegate = self
//coordinate for pin
var bridge17 = CLLocationCoordinate2DMake(53.346061, -6.227379)
//custom MKAnnotation
class MyAnnotation: NSObject, MKAnnotation {
#objc var coordinate: CLLocationCoordinate2D
var EXTRA_INFORMATION: String?
var title: String?
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
}
}
//setting information of pin
var bridge17pin = MyAnnotation()
bridge17pin.coordinate = bridge17
bridge17pin.title = "The bridge"
bridge17pin.subtitle = "hello this is the bridge"
bridge17pin.EXTRA_INFORMATION = "this was built in 2010"
mapView.addAnnotation(bridge17pin)
}
Because you have to send the coordinate while you are instantiating. So in the code replace
var bridge17pin = MyAnnotation()
with
var bridge17pin = MyAnnotation(coordinate: bridge17)
And for that subTitle see this link

Add a custom marker in mapbox in a for loop

I'm a little bit stuck here…
I'm trying to add a different image for each marker in my mapbox view. To populate the map I used a for loop that look into an array :
for arrayInterest in dicoInterest {
let point = MGLPointAnnotation()
var latitudePoint : Double
var longitudePoint : Double
var typePoint : String
latitudePoint = (arrayInterest["latitude"] as! Double)
longitudePoint = (arrayInterest["longitude"] as! Double)
typePoint = (arrayInterest["type"] as! String)
point.coordinate = CLLocationCoordinate2D(latitude: latitudePoint, longitude: longitudePoint)
mapView.addAnnotation(point)
print("latitude : \(latitudePoint)")
print("longitude : \(longitudePoint)")
print("point : \(point)")
print("type : \(typePoint)")
}
So far so good. The problem is, the only way to add a specific image I found looking online was this :
func mapView(mapView: MGLMapView, imageForAnnotation annotation: MGLAnnotation) -> MGLAnnotationImage? {
var annotationImage = mapView.dequeueReusableAnnotationImageWithIdentifier(typePoint)
var image = UIImage(named: typePoint)
image = image?.imageWithAlignmentRectInsets(UIEdgeInsetsMake(0, 0, image!.size.height/2, image!.size.width/2))
annotationImage = MGLAnnotationImage(image: image!, reuseIdentifier:"\(point)")
return annotationImage
}
I add to put that outside the loop, and therefore, it doesnt work for each marker.
Is there another way to do that ?
you still can add different images. this function will be called each time you add an marker, so can add a different image.
import UIKit
import Mapbox
class yourClassController: UIViewController{
//define an image var in your class
var markerImage = UIImage(name: "defaultMarker.png")
override func viewDidLoad() {
super.viewDidLoad()
//Set new image in yout loop
for arrayInterest in dicoInterest {
//new marker Image
markerImage = UIImage(name:newImageName)
}
}
}
// MARK: - MKMapViewDelegate// Use Extension
extension yourClassController: MGLMapViewDelegate {
func mapView(mapView: MGLMapView, imageForAnnotation annotation: MGLAnnotation) -> MGLAnnotationImage? {
let annotationImage = MGLAnnotationImage(image: markerImage, reuseIdentifier: "NewIdentiferName")
return annotationImage
}
}
It's important to set always a new reuseIdentifier for the image, otherwise it will take always the same image.
Code is not tested, but hope the principle is clear

Swift MapKit - add (extra)attribut to annotation?

I did this MapKit-Tutorial
Everything works fine, but how can I add an extra attribut to my pin?
This is my class Car:
import Foundation
import MapKit
class Car: NSObject, MKAnnotation {
let title: String
let subtitle: String
let thirdAttribut: String
let coordinate: CLLocationCoordinate2D
init(title: String, subtitle: String, thirdAttribut: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.thirdAttribut = thirdAttribut
self.coordinate = coordinate
super.init()
}
var getTitle: String {
return title
}
var getSubtitle: String {
return subtitle
}
var getThirdAttribut: String {
return thirdAttribut
}
I want click on an pin and work with this the "thirdAttribut".
My Main-Class:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
mapView.delegate = self
let car = Car(title: "Title", subtitle: "Subtitle", thirdAttribut: "ThirdAttribut", coordinate: CLLocationCoordinate2D(latitude: 50.906849, longitude: 7.524224) )
mapView.addAnnotation(car)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
//some config stuff
}
func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKAnnotationView!) {
print("Here Comes the Click")
print(view.annotation.title)
print(view.annotation.subtitle)
//view.annotation.thirdAttribut doesn't existis
//How get I my "thirdAttribut"-Attribut?
}
The third-Attribut mustn't appear in my view. It just contains some data for logic-operations.
I hope u understand me, english isn't my mother tongue.
If u know other ways to code what I want then please tell me. :)
Thank u!
An annotation view contains an annotation property. To get that third attribute, you need to cast MKAnnotation to the class you created that adheres to the MKAnnotation protocol, Car.
if let carAnnotation = view.annotation as? Car{
print(carAnnotation.thirdAttrib);
}