Show Annotation Title and SubTitle in Custom MKPinAnnotationView - ios

I am using MKPinAnnotationView inside my App.
I am setting MapView object as delegate, and using this code for customising my AnnotationView
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"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
// pinView!.canShowCallout = true
pinView!.image = UIImage(named:"store.jpg")
pinView!.animatesDrop = true
pinView!.pinTintColor = UIColor.darkGrayColor()
}
else {
pinView!.annotation = annotation
}
return pinView
}
I am getting custom AnnotationView as I required.However, I am missing the features of title and subtitle of MKPointAnnotation.
I wish to see title and subtitle for the grey dots.

I was overriding one func
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
mapView.deselectAnnotation(view.annotation, animated: true)
}
I commented this function out and got the titles and subtitles.
Updated Code
/*
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
mapView.deselectAnnotation(view.annotation, animated: true)
}
*/
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
pinView.accessibilityLabel = "hello"
let btn = UIButton(type: .DetailDisclosure)
pinView.rightCalloutAccessoryView = btn
return pinView
}

Related

Swift Mapview Custom Call Out View with default map view pins

I believe this is going to be a really easy answer but I've been trying to figure out how I add a custom callout view with map views default pins. With my current code it seems I can only add an image as the MKPointAnnotation instead of the default pins. This first "viewFor annotation" is how I set up the default pins, while everything underneath is for the custom call out view... What I am trying to do is have my custom call out view with the default pins. Do I have to add a custom image pin if I want a custom call out view?
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "") {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:"")
annotationView.isEnabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
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 = CustomBusinessCallOutAnnotatiion(annotation: annotation, reuseIdentifier: "Pin")
annotationView?.canShowCallout = false
}else{
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "car")
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if view.annotation is MKUserLocation { return }
let customAnnotation = view.annotation as! CustomBusinessPoint
let views = Bundle.main.loadNibNamed("CustomBusinessCallOut", owner: nil, options: nil)
let calloutView = views?[0] as! CustomBusinessCallOut
calloutView.businessName.text = customAnnotation.businessName
calloutView.businessStreet.text = customAnnotation.businessStreet
calloutView.businessState.text = customAnnotation.businessState
calloutView.businessDistance.text = customAnnotation.businessDistance
calloutView.center = CGPoint(x: view.bounds.size.width / 2, y: -calloutView.bounds.size.height * -0.0001)
view.addSubview(calloutView)
mapView.setCenter((view.annotation?.coordinate)!, animated: true)
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
if view.isKind(of: CustomBusinessCallOutAnnotatiion.self) {
for subview in view.subviews {
subview.removeFromSuperview()
}
}
}
You need not addSubView calloutView. You can use MKAnnotationView as Custom Callout.
e.g. You should arrange the source code
Implement subclass of MKAnnotation and MKAnnotationView.
class PinAnnotation : NSObject, MKAnnotation {
var coordinate : CLLocationCoordinate2D
var title: String?
var calloutAnnotation: CustomBusinessCallOut?
init(location coord:CLLocationCoordinate2D) {
self.coordinate = coord
super.init()
}
}
class CustomBusinessCallOut : NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
init(location coord:CLLocationCoordinate2D) {
self.coordinate = coord
super.init()
}
}
class CalloutAnnotationView : MKAnnotationView {
}
Implement mapView delegate methods.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if annotation is PinAnnotation {
let reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
}
else {
pinView?.annotation = annotation
}
return pinView
} else if annotation is CustomBusinessCallOut {
let reuseId = "Callout"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = CalloutAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.addSubview(UIImageView(image: UIImage(named: "car")))
}
else {
pinView?.annotation = annotation
}
return pinView
} else {
return nil
}
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard view.annotation is PinAnnotation else { return }
if let pinAnnotation = view.annotation as? PinAnnotation {
let calloutAnnotation = CustomBusinessCallOut(location: pinAnnotation.coordinate)
calloutAnnotation.title = pinAnnotation.title
pinAnnotation.calloutAnnotation = calloutAnnotation
mapView.addAnnotation(calloutAnnotation)
}
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
guard view.annotation is PinAnnotation else { return }
if let pinAnnotation = view.annotation as? PinAnnotation,
let calloutAnnotation = pinAnnotation.calloutAnnotation {
mapView.removeAnnotation(calloutAnnotation)
pinAnnotation.calloutAnnotation = nil
}
}

Swift map annotations

I am trying to get an annotation on the user location but I can't get a (sort of) speech bubble for my annotation's details. Is there any option to create something like this?
//AnnotationSettings
let newPin = MKPointAnnotation()
//set region on the map
maphome.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
newPin.title = "aksldfjaskldfjaklsdfa"
newPin.subtitle = "sounds awesome!"
maphome.addAnnotation(newPin)
This is my code for the annotation.
You should set canShowCallout = true.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKMarkerAnnotationView
if pinView == nil {
pinView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
yes, you can try this
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
// Always allow callouts to popup when annotations are tapped.
return true
}

Autosize annotation.title [duplicate]

I have a mapView with annotations displaying titles and subtitles. The subtitles are sometimes longer than the width of the annotation, so I am wondering if i can make them multiline?
It's coded like this so far:
func annotate(newCoordinate, title: String, subtitle: String) {
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinate
annotation.title = title
annotation.subtitle = subtitle
self.map.addAnnotation(annotation)
}
Then i have a few options set in
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {...}
which are not relevant here.
Is it posible to make a custom annotation view?
I've tried a couple of things, but nothing worked. The closest I can get is adding a button to display the longer subtitle separately, but i'd rather have it inside the annotation.
Is it possible?
I figured it out, I added a label in viewForAnnotation and it just worked
¯\_(ツ)_/¯
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"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
}
else {
pinView!.annotation = annotation
}
//THIS IS THE GOOD BIT
let subtitleView = UILabel()
subtitleView.font = subtitleView.font.fontWithSize(12)
subtitleView.numberOfLines = 0
subtitleView.text = annotation.subtitle!
pinView!.detailCalloutAccessoryView = subtitleView
return pinView
}

MKAnnotationView Swift Adding "Info" button

I am very new to swift (coming from python) I am struggling with creating a MKAnnotationView. I followed a tutorial by ray wenderlich but the code appears to be outdated. The function call does not seem to work or produce the "i" intended to be in the annotation of the pin. Here is the code I am currently using:
import MapKit
extension ViewController: MKMapViewDelegate {
// 1
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if let annotation = annotation as? Artwork {
let identifier = "pin"
var view: MKPinAnnotationView
if let dequeuedView = MapView.dequeueReusableAnnotationView(withIdentifier: identifier)
as? MKPinAnnotationView { // 2
dequeuedView.annotation = annotation
view = dequeuedView
} else {
// 3
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
let button = UIButton(type:.detailDisclosure)
view.rightCalloutAccessoryView = button as UIView
}
return view
}
return nil
}
}
I am running Xcode 8.1, any help will be greatly appreciated.
Am using Xcode 8.1 and Swift 3.0 . For Some reason Delegate methods are not firing until you set delegate in storyboard:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation {return nil}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
let calloutButton = UIButton(type: .DetailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}
return pinView
}
for button Action
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
print("button tapped")
}
}
I am attaching sample project for your issue
Map Sample Project Swift 3. 0 Xcode 8.1

Swift - MKPinAnnotation image issue

I'm trying to change my pin annotation image to something other than the pin.
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"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Green
pinView!.image = UIImage(named: "icon1.png")
// Add image to left callout
var mugIconView = UIImageView(image: UIImage(named: "test.png"))
pinView!.leftCalloutAccessoryView = mugIconView
// Add detail button to right callout
var calloutButton = UIButton.buttonWithType(.DetailDisclosure) as UIButton
pinView!.rightCalloutAccessoryView = calloutButton
}
else {
pinView!.annotation = annotation
}
return pinView
Everything works except changing the pin image. I have a custom point annotation subclass which is this
I've been searching for hours but every other SO question I've found hasn't helped. I'd appreciate any help... thanks.
UPDATED WITH ANSWER
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
}
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin")
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
pinView!.canShowCallout = true
pinView!.image = UIImage(named: "test.png")
// Add image to left callout
var mugIconView = UIImageView(image: UIImage(named: "test.png"))
pinView!.leftCalloutAccessoryView = mugIconView
// Add detail button to right callout
var calloutButton = UIButton.buttonWithType(.DetailDisclosure) as UIButton
pinView!.rightCalloutAccessoryView = calloutButton
}
else {
pinView!.annotation = annotation
}
return pinView
}
You want MKAnnotationView, not MKPinAnnotationView. Pin annotations can't customize their image.
See this SO answer for additional details

Resources