How to add a customView xib as annotation in Ios? - ios

when i am using googlemaps all I have to do is
let marker = GMSMarker()
marker.position = postions.target
marker.title = "TEST"
marker.map = self.mapView
let myCustomView:CustomView = UINib(nibName: "CustomView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CustomView
marker.iconView = myCustomView
but if i am using MAPKIT, how will I achieve this.?
Mycustomview is a xib view file i created.

Try to add the object of the nib view to the annotation view like this
func mapView(_ mapView: MKMapView,viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation == true
{
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 customView = (Bundle.main.loadNibNamed("directOrderView", owner: self, options: nil))?[0] as! directOrderView;
var calloutViewFrame = customView.frame;
calloutViewFrame.origin = CGPoint(x:-calloutViewFrame.size.width/2 + 30,y: -calloutViewFrame.size.height);
customView.frame = calloutViewFrame;
annotationView?.addSubview(customView)
return annotationView
}

ok i found the solution
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation
{
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil{
annotationView = AnnotationView(annotation: annotation, reuseIdentifier: "Pin")
annotationView?.canShowCallout = false
}else{
annotationView?.annotation = annotation
//annotationView?.canShowCallout = true
// mapView.deselectAnnotation(annotation, animated: true)
// mapView.selectAnnotation(annotation, animated: true)
}
let myCustomView:CustomView = UINib(nibName: "CustomView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CustomView
annotationView?.addSubview(myCustomView)
// annotationView?.image = UIImage(named: "starbucks")
return annotationView
}

Related

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

Update mapView pin colour based on boolean property

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
}

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) " )
}

Changing MKMapView User Location Annotation

I'm attempting to change the user default location annotation on the MKMapView from the blue to a custom image named geo. It's hitting the line to set it to geo when I set breakpoints, but both points (the user default, and Passenger point are default red pinpoint annotations) Am I setting this wrong, or is there certain image stipulations?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(PassengerLocation) == false {
//User location
let userIdentifier = "UserLocation"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(userIdentifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:userIdentifier)
}
annotationView!.annotation = annotation
annotationView!.canShowCallout = true
// THIS IS NOT WORKING, DEFAULT RED PIN POINT STILL SHOWING
annotationView!.image = UIImage(named: "geo")
return annotationView
}
let identifier = "PassengerLocation"
if let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.enabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .DetailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
This works:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isEqual(mapView.userLocation) {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
annotationView.image = UIImage(named: "geo")
return annotationView
}
}
its working for me
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// want to show a custom image if the annotation is the user's location.
guard !annotation.isKindOfClass(MKUserLocation) else {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
annotationView.image = UIImage(named: "icon_coordinates_self")
return annotationView
//return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "Annotation_map")
}
return annotationView
}
Use a regular MKAnnotationView if you want to customize the image. With a pin, all you can do is change the color.
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil
}
That works perfectly

change image pin maps

What should I write in order to put a personal picture instead of the traditional red pin?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annView : MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "currentloc")
annView.pinTintColor = UIColor.redColor()
annView.animatesDrop = true
annView.canShowCallout = true
annView.calloutOffset = CGPointMake(-8, 0)
annView.autoresizesSubviews = true
annView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
return annView
}
Use MKAnnotationView instead of MKPinAnnotationView, and then set its image property. I'd also suggest implementing the dequeue logic so that annotations can be reused:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationIdentifier = "SomeCustomIdentifier" // use something unique that functionally identifies the type of pin
var annotationView: MKAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView != nil {
annotationView.annotation = annotation
} else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView.image = UIImage(named: "annotation.png")
annotationView.canShowCallout = true
annotationView.calloutOffset = CGPointMake(-8, 0)
annotationView.autoresizesSubviews = true
annotationView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
}
return annotationView
}

Resources