Update mapView pin colour based on boolean property - ios

I'm trying to update the colour of the mapView pins based on whether the hotspot has been visited or not.
See my code below. Below is the hotspot class that subscribes to the MKAnnotation delegate. The property that determines pin colour is the visited Bool.
init(title: String, hotspotName: String,coordinate: CLLocationCoordinate2D, ARType:String, hotspotId:String)
{
//assing values to properties
self.hotspotTitle = title
self.hotspotName = hotspotName
self.ARType = ARType
self.coordinate = coordinate
self.hotspotId = hotspotId
super.init()
}
var visited: Bool {
return self.completed
}
var title: String?
{
return hotspotTitle
}
var subtitle: String?
{
return hotspotName
}
Below is the mapKit delegate method I'm using to try and update pin colour.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// check if annotation is of type Hotspot, as we dont want to alter other types of annotations
guard annotation is Hotspot else {
return nil
}
let identifier = "Hotspot"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
let pinView = MKPinAnnotationView(annotation:annotation,reuseIdentifier: identifier)
if annotationView == nil
{
if let hotspot = annotationView?.annotation as? Hotspot {
if !hotspot.visited
{
pinView.pinTintColor = UIColor(red:0.32, green:0.82, blue:0.4, alpha:1)
pinView.tintColor = UIColor(white: 0.0, alpha: 0.5)
}
else
{
pinView.pinTintColor = UIColor(red:0.0, green:0.0, blue:0.90, alpha:1)
pinView.tintColor = UIColor(white: 0.0, alpha: 0.5)
}
}
pinView.frame = mapView.frame
pinView.isEnabled = true
pinView.canShowCallout = true
pinView.animatesDrop = true
let rightButton = UIButton(type: .detailDisclosure)
rightButton.addTarget(self,action: #selector(getDirections),for: .touchUpInside)
pinView.rightCalloutAccessoryView = rightButton
annotationView = pinView
}
if let annotationView = annotationView
{
annotationView.annotation = annotation
// 5
let button = annotationView.rightCalloutAccessoryView as! UIButton
if let index = trail.hotspots.index(of: annotation as! Hotspot)
{
button.tag = index
}
}
return annotationView
}

Update mapView pin colour out of if annotationView == nil statement.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// check if annotation is of type Hotspot, as we dont want to alter other types of annotations
guard annotation is Hotspot else {
return nil
}
let identifier = "Hotspot"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
let pinView = MKPinAnnotationView(annotation:annotation,reuseIdentifier: identifier)
if annotationView == nil
{
pinView.frame = mapView.frame
pinView.isEnabled = true
pinView.canShowCallout = true
pinView.animatesDrop = true
let rightButton = UIButton(type: .detailDisclosure)
rightButton.addTarget(self,action: #selector(getDirections),for: .touchUpInside)
pinView.rightCalloutAccessoryView = rightButton
annotationView = pinView
}
if let hotspot = annotationView?.annotation as? Hotspot {
if !hotspot.visited
{
annotationView.pinTintColor = UIColor(red:0.32, green:0.82, blue:0.4, alpha:1)
annotationView.tintColor = UIColor(white: 0.0, alpha: 0.5)
}
else
{
annotationView.pinTintColor = UIColor(red:0.0, green:0.0, blue:0.90, alpha:1)
annotationView.tintColor = UIColor(white: 0.0, alpha: 0.5)
}
}
if let annotationView = annotationView
{
annotationView.annotation = annotation
// 5
let button = annotationView.rightCalloutAccessoryView as! UIButton
if let index = trail.hotspots.index(of: annotation as! Hotspot)
{
button.tag = index
}
}
return annotationView
}

Related

how to change default image in MKUserLocation annotation in Swift iOS

I have a map view in my app that displays the user's location. when the user's location is tapped an image is displayed as below:
is there a way to make this image customized to my liking, so for instance I would like to show the photo that the user has in his own profile, or any other static image that I would like to add.
similar to how the apple maps would show your profile picture in your location dot.
how can I do that here?
here is my code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
print("user location image tapped")
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true
pinView?.canShowCallout = true
pinView?.isDraggable = true
// pinView?.pinColor = .purple
let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
any help on this? thank you.
let imageView = UIImageView(frame: CGRect(0, 0, 25, 25))
imageView.image = UIImage(named: "userpic");
imageView.layer.cornerRadius = imageView.layer.frame.size.width / 2
imageView.layer.masksToBounds = true
anotationView.frame = imageView.frame

Swift Annotation Custom Image

I'm using Swift 3 and Xcode 10 beta 3 and I need to use a custom image for my pins on the map. After the help of a guy on another post we made this code, it's all working except the pins are still the default.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? Annotation {
let identifier = "identifier"
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.image = annotation.image //add this
annotationView.canShowCallout = true
annotationView.calloutOffset = CGPoint(x: -5, y: 5)
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
return annotationView
}
return nil
}
let marker = Annotation(title: "LVR" , subtitle: "" , coordinate: CLLocationCoordinate2D(latitude: 43.772523, longitude: 11.254356))
marker.image = UIImage(named: "antonioli.png")
//mapView.addAnnotation(marker)
self.map.addAnnotation(marker)
The PNG file is in the main folder of my project like this:
How should I handle this problem?
Here MyAnnotation is a subclass of NSObject, MKAnnotation
func mapView(_ mapView: MKMapView,viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MyAnnotation == false
{
return nil
}
let senderAnnotation = annotation as! MyAnnotation
let pinReusableIdentifier = senderAnnotation.pinColor.rawValue
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pinReusableIdentifier)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: senderAnnotation, reuseIdentifier: pinReusableIdentifier)
annotationView!.canShowCallout = true
}
let pinImage = UIImage(named:"location_curr.png")
annotationView!.image = pinImage
return annotationView
}
See Demo MapCustomImage

Open NavigationController on tap of button in MKAnnotationView

I have MKAnnotationView where I am showing title,subtitle and info button, on tap of location pin.
I have added the following code
func mapView(mapView: 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"
let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView.canShowCallout = true
pinView.animatesDrop = true
pinView.pinTintColor = UIColor.darkGrayColor()
pinView.draggable = true
let btn = UIButton(type: .DetailDisclosure)
pinView.rightCalloutAccessoryView = btn
let tapGesture = UITapGestureRecognizer(target: self,action: #selector(MapView.calloutTapped(_:)))
pinView.addGestureRecognizer(tapGesture)
return pinView
}
func calloutTapped(sender: UITapGestureRecognizer) {
// if sender.state != UIGestureRecognizerState.Began { return }
let annView: MKAnnotationView! = sender.view as? MKAnnotationView
let ann:MKAnnotation! = annView!.annotation
print("handlePinButtonTap: ann.title \(ann!.title!!) and \(ann!.subtitle!!)")
let touchLocation = sender.locationInView(mapView)
let locationCoordinate = mapView.convertPoint(touchLocation, toCoordinateFromView: mapView)
print("Tapped at lat: \(locationCoordinate.latitude) long: \(locationCoordinate.longitude) " )
let storyboard : UIStoryboard = UIStoryboard(name: "ShoppingCart", bundle: nil)
let vc : ShoppingCartController = storyboard.instantiateViewControllerWithIdentifier("ShoppingCart") as! ShoppingCartController
let navigationController = UINavigationController(rootViewController: vc)
self.presentViewController(navigationController, animated: true, completion: nil)
}
However upon using this code,on tap of the pin on the map, user is navigated to the ShoppingCart storyboard. I want to present that ViewController on the tap of info button along with the title,subtitle, latitude and longitude of the event that has been tapped.
Here is the working solution
func mapView(mapView: 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"
let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView.canShowCallout = true
pinView.animatesDrop = true
pinView.pinTintColor = UIColor.darkGrayColor()
pinView.draggable = true
let btn = UIButton(type: .DetailDisclosure)
pinView.rightCalloutAccessoryView = btn
let tapGesture = UITapGestureRecognizer(target: self,action: #selector(MapView.calloutTapped(_:)))
pinView.addGestureRecognizer(tapGesture)
return pinView
}
func calloutTapped(sender: UITapGestureRecognizer) {
// if sender.state != UIGestureRecognizerState.Began { return }
let annView: MKAnnotationView! = sender.view as? MKAnnotationView
let ann:MKAnnotation! = annView!.annotation
print("handlePinButtonTap: ann.title \(ann!.title!!) and \(ann!.subtitle!!)")
let touchLocation = sender.locationInView(mapView)
let locationCoordinate = mapView.convertPoint(touchLocation, toCoordinateFromView: mapView)
print("Tapped at lat: \(locationCoordinate.latitude) long: \(locationCoordinate.longitude) " )
}

MKMapView annotation tap on subview

I'm trying to implement an annotation with user picture, it works, but then, tap annotation recognition stops working.
How can I delegate subview tap to map ?
Here is my override function
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(MKUserLocation) {
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil
{
let imgUserPic: UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
if (userPic != nil) {
imgUserPic.autoresizingMask = UIViewAutoresizing.FlexibleBottomMargin.intersect(UIViewAutoresizing.FlexibleHeight).intersect(UIViewAutoresizing.FlexibleRightMargin).intersect(UIViewAutoresizing.FlexibleLeftMargin).intersect(UIViewAutoresizing.FlexibleTopMargin).intersect(UIViewAutoresizing.FlexibleWidth)
imgUserPic.contentMode = UIViewContentMode.ScaleAspectFill
imgUserPic.layer.cornerRadius = 30
imgUserPic.layer.masksToBounds = true
imgUserPic.layer.borderColor = UIColor.whiteColor().CGColor
imgUserPic.layer.borderWidth = 1.0
imgUserPic.image = userPic
imgUserPic.userInteractionEnabled = true
let info: MKPointAnnotation = MKPointAnnotation()
info.title = NSLocalizedString("MYLOCATION", comment: "")
info.coordinate = annotation.coordinate
anView = MKAnnotationView(annotation: info, reuseIdentifier: reuseId)
anView?.addSubview(imgUserPic)
anView?.calloutOffset = CGPointMake(0, 32)
anView!.canShowCallout = true
}
} else {
anView?.annotation = annotation
}
return anView
} else {
return nil
}
}

MKAnnonationView transparent

i'm trying to create a MKAnnonationView, but when i tap the annonations they appear with a transparent background. When i press the segmentControllr which shows tableView instead of MKMapView then its white until i tap the annonation again then it become transperent again.
viewdidLoad
pointMapView = MKMapView(frame: CGRectMake(0, 0, self.tableView.frame.width, self.tableView.frame.height))
pointMapView?.showsUserLocation = true
add MKAnnonations
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()
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let theImage = UIImage(data:imageData)
pinView.itemImage = theImage
pinView.setCoordinate(coordinate)
pinView.title = titleString
pinView.subtitle = dateString
self.pointMapView!.addAnnotation(pinView)
}
}
viewForAnnonation
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 rightButton: AnyObject! = UIButton.buttonWithType(UIButtonType.DetailDisclosure)
//MapPointAnnotation *point = (MapPointAnnotation*)pinView.annotation;
//rightButton.venue = point.venue;
rightButton.titleForState(UIControlState.Normal)
rightButton.addTarget(self, action: "rightButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
pinView!.rightCalloutAccessoryView = rightButton as UIView
var leftImage: UIImageView = UIImageView(frame: CGRectMake(0, 0, 44, 44))
leftImage.image = annotation.itemImage
pinView!.leftCalloutAccessoryView = leftImage
}
else {
pinView!.annotation = annotation
}
return pinView
}

Resources