I have run into a slight problem. I am trying to use a custom icon for my mapView annotation. The trouble is that when the user drags the icon it always changes back to the default icon.
I set the icon image in my mapView delegate like so, this works to set the icon.
// MARK: - Map Annotations
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation{
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if(pinView == nil){
if let customAnnot = annotation as? myAnnotation {
pinView = MKPinAnnotationView(annotation: customAnnot, reuseIdentifier: reuseId)
pinView!.image = UIImage(named:"pin-50.png")
pinView!.animatesDrop = false
pinView!.draggable = true
}
} else {
pinView!.annotation = annotation as? myAnnotation
}
return pinView!
}
I tried a few things to fix but none have seem to helped. even when I try to set the icon again in the "didChangeDragState" delegate it still changes to default icon.
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
if newState == MKAnnotationViewDragState.Dragging {
println("draggin it")
view.image = UIImage(named:"pin-50.png")
}
if newState == MKAnnotationViewDragState.Ending {
//update pin location
if let customAnnot = view.annotation as? myAnnotation {
cData.updatePinLocation(customAnnot.pinID, newValue: customAnnot.coordinate)
}
view.image = UIImage(named:"pin-50.png")
}
if newState == MKAnnotationViewDragState.Starting {
println("start drag")
view.image = UIImage(named:"pin-50.png")
}
}
Thanks to zisoft, I figured it out. here is the code that works
if (annotation is MKUserLocation) {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView.image = UIImage(named:"pin-50.png")
pinView.canShowCallout = false
pinView.draggable = true
}
else {
pinView.annotation = annotation
}
return pinView
Related
What I'm trying to do is to display a custom annotation view on a map view (MKMapView), that is working fine in the app.
The problem is when I'm switching between apps or changing between dark & light modes the custom annotation view seems to revert to the default annotation pin as shown below.
Deployment Target: iOS 11
Running on: iPhone XS MAX iOS 13.3
Xcode Version: 11.3 (11C29)
Swift Version: 5.0
private func addAnnotations(_ places : [QPPlaceDM]) {
mapView.removeAnnotations(myAnnotations)
var annotations = [MKPointAnnotation]()
for item in places {
let annotation = QPCustomAnnotaion()
annotation.title = item.name
annotation.coordinate = item.coordinates
annotation.image = item.category.pinImage
annotations.append(annotation)
}
myAnnotations = annotations
mapView.addAnnotations(myAnnotations)
}
.......
extension QPMainVC : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is QPCustomAnnotaion) {
return nil
}
let annotationID = "AnnotationId"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationID)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationID)
annotationView?.canShowCallout = true
}
else {
annotationView?.annotation = annotation
}
let myCustomAnnotation = annotation as? QPCustomAnnotaion
annotationView?.image = myCustomAnnotation?.image
annotationView?.displayPriority = .required
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotationLocation = view.annotation?.coordinate else { return }
var indexOfAnnotation = 0
for (index , item) in myAnnotations.enumerated() {
if annotationLocation.latitude == item.coordinate.latitude{
indexOfAnnotation = index
break
}
}
let indexPathOfMagorCell = IndexPath(row: indexOfAnnotation, section: 0)
placesCollection.scrollToItem(at: indexPathOfMagorCell, at: .centeredHorizontally, animated: true)
}
}
Working properly
After app switching
Switching from MKPinAnnotationView to MKAnnotationView in the viewFor annotation func fixed this issue for me:
Old:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomMapItemAnnotation) { return nil }
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "id")
if (annotation is CustomMapItemAnnotation) {
annotationView.canShowCallout = true
if let placeAnnotation = annotation as? CustomMapItemAnnotation {
if let type = placeAnnotation.type {
print("\(type)-color")
annotationView.image = UIImage(named: "\(type)-color")
}
}
}
return annotationView
}
New:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomMapItemAnnotation) { return nil }
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "id")
if (annotation is CustomMapItemAnnotation) {
annotationView.canShowCallout = true
if let placeAnnotation = annotation as? CustomMapItemAnnotation {
if let type = placeAnnotation.type {
print("\(type)-color")
annotationView.image = UIImage(named: "\(type)-color")
}
}
}
return annotationView
}
I am working in map view annotation.
The marker annotation should be displayed using the parking rule type
If paid pin image be "paid" and if free pin image be "free"
I am getting all annotation as "paid" image
I have attached my code below can any one help me in this issue to fix
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
if let annotationView = annotationView {
// Configure your annotation view here
if parkingTypeArray.count > 0 {
for cameraa in parkingTypeArray.enumerated() {
if cameraa.element == "Free street parking" {
let pinImage = UIImage(named: "free")
annotationView.image = pinImage
}else if cameraa.element == "Paid street parking" {
let pinImage = UIImage(named: "paid")
annotationView.image = pinImage
}else if cameraa.element == "Paid parking" {
let pinImage = UIImage(named: "paid")
annotationView.image = pinImage
}
}
}
}
return annotationView
}
Same thing I Have Done with Custom MKPointAnnotation Class
class MyPointAnnotation : MKPointAnnotation {
var obj : ComparableData?
init(data_obj : ComparableData) {
self.obj = data_obj
super.init()
}
}
Setup Map
for item in self.Arr_Map_Comparables{
if item.Latitude != "" && item.Longitude != ""{
let annotation = MyPointAnnotation(data_obj: item)
annotation.coordinate = CLLocationCoordinate2D(latitude: Double(item.Latitude!)!, longitude: Double(item.Longitude!)!)
annotation.title = item.Full_Address
mapView.addAnnotation(annotation)
}
}
self.focusMarkers(markers: mapView.annotations, width: 50)
MapView Delegate Methods
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
if let annotation = annotationView.annotation as? MyPointAnnotation{
if annotation.obj?.Status_Mls == "Active"{
annotationView.image = UIImage(named: "active")
}else if annotation.obj?.Status_Mls == "Sold"{
annotationView.image = UIImage(named: "sold")
}else{
annotationView.image = UIImage(named: "other")
}
}
}
return annotationView
}
So my code works fine but my logger is riddled with this message. Is there a way to get rid of it or suppress it?
PostAnnotation.swift
class PostAnnotation: MKPointAnnotation {
//MARK: properties
let post: Post
//MARK: initialization
init(post: Post) {
self.post = post
super.init()
self.coordinate = CLLocationCoordinate2D(latitude: post.latitude, longitude: post.longitude)
self.title = post.title
self.subtitle = post.timeString()
}
}
Adding the annotation
let annotation = PostAnnotation(post: post)
self.map.addAnnotation(annotation)
func mapView
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "pin") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? PostAnnotation {
annotationView?.pinTintColor = UIColor.blue
annotationView?.canShowCallout = true
annotationView?.rightCalloutAccessoryView = UIButton(type: .infoLight)
annotationView?.animatesDrop = true
}
return annotationView
}
Removing this function removes the message
This is a bug in iOS 11, since MKLayer is not a public class.
I'd simply ignore the message, but if it's bothering you: To silence this warning, you can set OS_ACTIVITY_MODE=disable in the scheme's environment page. Beware though, you will silence other OS warnings as well.
I am trying to rotate an image for a MKAnnotation and while I succeed to do so, the title of it is also rotating. Is there a way to keep the title straight? Any help would be really appreciated!
Here is my code:
In viewDidLoad():
let middlePoint = CustomPointAnnotation()
middlePoint.coordinate = self.coordinates
middlePoint.imageName = "routemiddle"
middlePoint.title = "\(hourDetailedRoute):\(minuteDetailedRoute)"
middlePoint.courseDegrees = self.vehicleChangeCourse
self.mapa.addAnnotation(middlePoint)
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "annotation"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView!.canShowCallout = true
}
else {
anView!.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
anView!.image = UIImage(named:cpa.imageName)
anView!.transform = CGAffineTransformRotate(self.mapa.transform, CGFloat(degreesToRadians(cpa.courseDegrees)))
return anView
}
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
var courseDegrees = 0.0
}
I have figured it out! I just needed to rotate only the image instead of rotating the whole view.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "annotation"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView!.canShowCallout = true
}
else {
anView!.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
var imagePin = UIImage(named:cpa.imageName)
imagePin = imagePin?.rotateImage(cpa.courseDegrees)
anView!.image = imagePin
return anView
}
I try to create a custom "badget" for my MKPointAnnotation in swift, but it fails as MKPointAnnotation does not have any property like image
var information = MKPointAnnotation()
information.coordinate = location
information.title = "Test Title!"
information.subtitle = "Subtitle"
information.image = UIImage(named: "dot.png") //this is the line whats wrong
Map.addAnnotation(information)
Anyone figured out a swift like solution for that?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is MKPointAnnotation) {
return nil
}
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("demo")
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "demo")
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "image")
return annotationView
}