I am facing a problem about show multiple annotation on MKMapView. My question is that, I have three type annotation like as(select_StarFlag, simple_Flag, currentLocation_Flag). all flag are show on map but there are interchange the position between them, when I scroll the map, some Flag overlap each other. I am using following code
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if (annotation.isKindOfClass(MKUserLocation)) {
//if annotation is not an MKPointAnnotation (eg. MKUserLocation),
//return nil so map view draws"Blue Dot" for standard user location
return nil
}
if (annotation.isKindOfClass(MKPointAnnotation)){
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as MKAnnotationView!
if (anView == nil) {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
var data = Double(annotation.coordinate.latitude)
var data1 = Double(annotation.coordinate.longitude)
var flag = Bool(false)
for geoData in ysDataBaseGeolocationArray{
var geolocationlat = Double()
var geolocationlong = Double()
geolocationlat = Double(geoData.objectAtIndex(0) as NSNumber)
geolocationlong = Double(geoData.objectAtIndex(1) as NSNumber)
if data == geolocationlat && data1 == geolocationlong {
println(geolocationlat)
println(geolocationlong)
flag = true
break
}
}
if flag {
anView.image = UIImage(named:"select_StarFlag")
}
else if data == Double(ysLatitude) && data1 == Double(ysLongitude){
if ysValueFlag != false{
anView.image = UIImage(named:"currentLocation_Flag")
}else {
anView.image = UIImage(named:"simple_Flag")
}
}
else {
anView.image = UIImage(named:"simple_Flag")
}
}
else {
//we are re-using a view, update its annotation reference..
anView.canShowCallout = true
anView.annotation = annotation
}
return anView
}
return nil
}
Related
I'm trying to change pin colour based on a variable - the colour of certain pins change but it seems random and doesn't relate to the colour that I'm expecting. I suspect it's something to do with dequeueReusableAnnotationView.I have tried without but I got the same results. Any ideas ? Thanks
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard annotation is MKPointAnnotation else { return nil }
let identifier = "Annotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
let pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
pin.canShowCallout = true
annotationView = pin
if globalDataSet[counter].fields.numdocksavailable == 0 {
print (counter,globalDataSet[counter].fields.numdocksavailable, globalDataSet[counter].fields.name)
print ("pin.pinTintColor = UIColor.systemBlue")
pin.pinTintColor = UIColor.systemBlue
} else {
print (counter,globalDataSet[counter].fields.numdocksavailable, globalDataSet[counter].fields.name)
print ("pin.pinTintColor = UIColor.systemRed")
pin.pinTintColor = UIColor.systemRed
}
counter += 1
} else {
annotationView!.annotation = annotation
}
return annotationView
}
Try the following code.
if annotationView == nil {
let pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
pin.canShowCallout = true
annotationView = pin
} else {
annotationView!.annotation = annotation
}
if globalDataSet[counter].fields.numdocksavailable == 0 {
print (counter,globalDataSet[counter].fields.numdocksavailable, globalDataSet[counter].fields.name)
print ("annotationView.pinTintColor = UIColor.systemBlue")
annotationView.pinTintColor = UIColor.systemBlue
} else {
print (counter,globalDataSet[counter].fields.numdocksavailable, globalDataSet[counter].fields.name)
print ("annotationView.pinTintColor = UIColor.systemRed")
annotationView.pinTintColor = UIColor.systemRed
}
counter += 1
I have setup a map in which data is loaded from the parse backend. In map I want to display the images that are already saved in Assets folder. Image should be equal to Player Name . There latitude and longitude is already saved in the Parse.
The position of the player is displayed correctly but the image is not being showed correctly , if the last name in the playerName column is Sachin then the image is same for all the player annotation pin.
I want to apply like if playerName == annotation.title the image of rahul should be displayed .
Console Print :
26.6481591686873 , 77.1777485870544 Sachin
27.655116868732 , 77.17778705437 Rahul
28.6479996556687 , 77.1779252453013 Matt
28.6480628887157 , 77.1779590059193 Virat
28.1578689896 , 76.989079 Sachin
var playerName:String!
override func viewDidLoad() {
super.viewDidLoad()
query.findObjectsInBackgroundWithBlock { (posts, error) in
if error == nil {
let myPosts = posts! as [PFObject]
for posts in myPosts {
let latitude12 = posts["playerLat"] as! Double
let longitude12 = posts["playerLong"] as! Double
let playName = posts["playerName"] as! String
self.playerName = posts["playerName"] as! String
print(latitude12,"," , longitude12, playerName)
let annotation = MKPointAnnotation()
//let customAnno = MKAnnotationView()
let locationCoordinate = CLLocationCoordinate2DMake(latitude12, longitude12)
annotation.coordinate = locationCoordinate
//customAnno.enabled = true
let anno = self.mapView.dequeueReusableAnnotationViewWithIdentifier("places")
if anno == nil {
// if annotation.title == "Sachin" {
//}
annotation.title = playerName
self.mapView.addAnnotations([annotation])
} else {
anno?.annotation = annotation
}
}
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "customAnnotationView"
let annotation1 = MKPointAnnotation()
// custom image annotation
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if (annotationView == nil) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
else {
annotationView!.annotation = annotation
}
if annotation1.title == "Rahul" {
annotationView!.image = UIImage(named: "Rahul")}
else if annotation1.title == "Sachin"{
annotationView!.image = UIImage(named: "Sachin")
}
return annotationView
}
I have tried all codes but the image is same for all the players image.
I have an array of 4 locations, and an array of 4 pin names (ie "bluePin.png | redPin.png | etc...")
Currently I'm using a bit of code I found elsewhere to add custom pin graphics to all 4 locations, but all of my pins are red.
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
let annotationReuseId = "Truck"
var trkPin = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationReuseId)
if trkPin == nil {
trkPin = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationReuseId)
} else {
trkPin!.annotation = annotation
}
trkPin!.image = UIImage(named: "redPin.png")
trkPin!.backgroundColor = UIColor.clearColor()
trkPin!.canShowCallout = false
return trkPin
}
How could I associate the pin colors with the locations in the array, so that each location is differentiated by color?
Thanks!
I have done this in the simple way by declaring array of location and array images. And I have viewDidLoad method as follows.
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
let location = [
CLLocationCoordinate2D(latitude: 12, longitude: 77),
CLLocationCoordinate2D(latitude: 12.5, longitude: 77.5),
CLLocationCoordinate2D(latitude: 13, longitude: 78),
CLLocationCoordinate2D(latitude: 13.5, longitude: 78)
]
let pins = [
"red.png",
"blue.png",
"green.png",
"yellow.png"
]
var annotations = [MKPointAnnotation]()
for (index, eachLocation) in location.enumerate() {
let pinImageName = pins[index]
let annotation = MKPointAnnotation()
annotation.coordinate = eachLocation
annotation.title = "\(pinImageName)"
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
And in the viewForAnnotation delegate method just getting that image name from the title property and explicitly disabling the callout
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let annotationReuseId = "Truck"
var trkPin = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationReuseId)
if trkPin == nil {
trkPin = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationReuseId)
trkPin!.canShowCallout = false
} else {
trkPin!.annotation = annotation
if let image = annotation.title {
trkPin!.image = UIImage(named: image ?? "default.png")
} else {
trkPin!.image = UIImage(named: "default.png")
}
}
return trkPin
}
I wonder how to set different images to annotation pins on mapview. The difference between the following questions
viewForAnnotation confusion and customizing the pinColor iteratively
Swift different images for Annotation
is that my array of images is generated dynamically with regard to server response. There is no fixed size of the array, so switch/case construction is not a good idea. Moreover, I'm not sure how to apply the solution with custom class aforementioned in topic above. I'm aware that it would be better to post a comment to one of the questions asked before, but unfortunately I'm too rookie at the moment to do that(too few points).
This is the for loop performed inside functions that shows map:
for var r=0;r<arrayOfRestaurants.count;r++
{
var summonRestaurant:NSDictionary = arrayOfRestaurants[r] as NSDictionary
var nearbyRestaurant = Restaurant(nearbyRestaurants:summonRestaurant)
var latRestaurant=(nearbyRestaurant.latitude as NSString).doubleValue
var longRestaurant=(nearbyRestaurant.longitude as NSString).doubleValue
var locationOfRestaurant = CLLocationCoordinate2D(
latitude: latRestaurant as CLLocationDegrees, longitude: longRestaurant as CLLocationDegrees)
var lunchArray: NSArray = nearbyRestaurant.lunch as NSArray
var annotation = MKPointAnnotation()
annotation.setCoordinate(locationOfRestaurant)
annotation.title = nearbyRestaurant.name + " " + nearbyRestaurant.distance + " km"
map.addAnnotation(annotation)
}
And here is viewForAnnotation delegate method(quite identical to the method used in aforementioned threads):
func mapView(map: 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 = map.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Purple
pinView!.image = globalImageArray[0]
}
else {
pinView!.annotation = annotation
}
return pinView
}
As you can see, I assigned a certain image to pinView which is globalImageArray[0], but I look for a solution that let me iterate over the globalImageArray and assign a certain image to each pin.
I'd be glad to receive any help, thanks in advance!
First, you need to create your own class that adopts the MKAnnotation protocol for your annotations -
class RestaurantAnnotation : NSObject, MKAnnotation {
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
}
}
Then, use instances of this class when you add the annotation and set the image -
for var r=0;r<arrayOfRestaurants.count;r++
{
var summonRestaurant:NSDictionary = arrayOfRestaurants[r] as NSDictionary
var nearbyRestaurant = Restaurant(nearbyRestaurants:summonRestaurant)
var latRestaurant=(nearbyRestaurant.latitude as NSString).doubleValue
var longRestaurant=(nearbyRestaurant.longitude as NSString).doubleValue
let locationOfRestaurant = CLLocationCoordinate2D(
latitude: latRestaurant as CLLocationDegrees, longitude: longRestaurant as CLLocationDegrees)
var lunchArray: NSArray = nearbyRestaurant.lunch as NSArray
let title = nearbyRestaurant.name + " " + nearbyRestaurant.distance +" km"
var annotation = RestaurantAnnotation(coordinate, title:title, subtitle:"")
annotation.image = globalImageArray[r]
map.addAnnotation(annotation)
}
Now, in your view for annotation you can access the image -
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is RestaurantAnnotation) {
return nil
}
let reuseId = "restaurant"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
let restaurantAnnotation = annotation as RestaurantAnnotation
if (restaurantAnnotation.image != nil) {
anView.image = restaurantAnnotation.image!
anView.image.layer.setCornerRadius(8.0)
anView.image.layer.clipsToBounds=true
}
else {
// Perhaps set some default image
}
return anView
}
I'm trying to show a set of parse objects in a MKMapView as Annonations. This seem to work, the problem is that the objects images are swapped, which is kind of random? i've started creating a subclass of the MKPointAnnotation in order to save the image. How come the images are swapped around?
Custom MKPointAnnonation class
class AnnonationClass: MKPointAnnotation {
var itemId: NSString?
var itemImage: PFFile?
var itemdescription: NSString?
}
getting the parse objects and adding them using the setGeoPoint method
override func objectsDidLoad(error: NSError!) {
super.objectsDidLoad(error)
if error == nil {
self.pointMapView?.removeAnnotations(pointMapView?.annotations)
for object in objects {
var theObject = object as PFObject
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd" // superset of OP's format
let str = dateFormatter.stringFromDate(object.createdAt)
self.setGeoPoint(theObject.objectForKey("location") as PFGeoPoint, titleString: theObject.objectForKey("title") as NSString, imageFile: theObject.objectForKey("image") as PFFile, theId: theObject.objectId as NSString, descString: theObject.objectForKey("description") as NSString, dateString: str)
}
}
}
Setting the coordinates, title and saving the imageFile in the itemImage
func setGeoPoint(geoPoint:PFGeoPoint, titleString:NSString, imageFile:PFFile, theId:NSString, descString:NSString, dateString:NSString) {
var coordinate = CLLocationCoordinate2DMake(geoPoint.latitude, geoPoint.longitude) as CLLocationCoordinate2D
var pinView:AnnonationClass = AnnonationClass()
pinView.itemImage = imageFile
pinView.setCoordinate(coordinate)
pinView.title = titleString
pinView.subtitle = dateString
self.pointMapView!.addAnnotation(pinView)
}
creating the image and setting it
func mapView(mapView: MKMapView!, viewForAnnotation annotation: AnnonationClass!) -> MKAnnotationView! {
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
var leftImage: PFImageView = PFImageView(frame: CGRectMake(0, 0, 44, 44))
leftImage.file = annotation.itemImage
leftImage.loadInBackground()
pinView!.leftCalloutAccessoryView = leftImage
}
else {
pinView!.annotation = annotation
}
return pinView
}
In your viewForAnnotation, when pinView != nil, i.e. when reusing a view, it could well be that the image is set from the previous time that view was used. I think it is analogous to setting check marks on table view cells instead of using the data source to properly set properties for the cell contents.
Try setting the image view whether or not the pinView is reused.
func mapView(mapView: MKMapView!, viewForAnnotation annotation: AnnonationClass!) -> MKAnnotationView! {
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
}
var leftImage: PFImageView = PFImageView(frame: CGRectMake(0, 0, 44, 44))
leftImage.file = annotation.itemImage
leftImage.loadInBackground()
pinView!.leftCalloutAccessoryView = leftImage
return pinView
}