1

This is my first foray into the app world so it's taken a lot of research to get to this point. I'm building a map application and am going for an interface similar to the zillow app seen below. I am trying to come up with the right approach that allows me to click on a map annotation and it brings up a smaller view where I can interact with it. So essentially I have a few questions:

  1. Should I use a subview inside the map controller, or use a container view. Or is there another approach I haven't seen?

  2. How do I push data from the annotation to that function?

  3. How do I keep this subview hidden until an annotation has been clicked?

So far this is the closest thing I can find: Customize MKAnnotation Callout View?

Thanks!

enter image description here

Community
  • 1
  • 1
petfreshman
  • 513
  • 2
  • 8
  • 21

1 Answers1

0

I am new to iOS also, but I have done something similar to what you want to do. I have a view that shows some statistics, speed, bearing, etc. When someone clicks on the annotation, I toggle showing and hiding the statistics. There may be better ways, but here is what I did.

"Executive summary for your questions"

1 and 3) Use a subview over the map that you hide and unhide

2) Subclass both MKAnnotation and MKAnnotationView. Put the data you want to pass in a property of the subclassed MKAnnotationView, and then transfer the property to the MKAnnotationView when you create it. You can then retrieve it from the view passed in to didSelectAnnotationView.

Details

1) and 3) I created a subview that sits on the mapView and set it as hidden in the story board initially. I then have a toggeleMarkerStatistics() func tion that toggles the visibility of the view. So something like this

func toggleMarkerStatistics() {
  if mapMarkerStatistics.hidden {
    mapMarkerStatistics.hidden = false
  } else {
    mapMarkerStatistics.hidden = true
  }
}

This function is called from within

func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) { }

2) To get data into the didSelectAnnotationView, here is what I did. I subclassed both MKAnnotation and MKAnnotationView and added properties to hold the data that I wanted to pass to didSelectAnnotationView. So something like this:

class MyAnnotation: MKPointAnnotation {
  var myMarker: MyMapMarker?
}

class MyMKAnnotationView: MKAnnotationView {  
  var myMarker: MyMapMarker?  
}

When you create the annotation, set the property, before you add the annotation to the map.

let annotation = MyAnnotation()
annotation.myMarker = marker
annotation.coordinate = location
annotation.title = "btw, you MUST have a title or bad things happen"
mapView.addAnnotation(annotation)

Then in viewForAnnotation, you will be given your custom annotation with the property you set after you created it and you are asked to create a view for this annotation. Now when you create this view, set the view property to annotation property before you return the view. Now the data you want to pass to didSelectAnnotationView will be available on the view passed to didSelectAnnotationView

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    let view: MKAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier("marker")  ?? MyMKAnnotationView(annotation: annotation, reuseIdentifier: "marker")
    view.annotation = annotation
    view.canShowCallout = false  // you need this to make this work
    if let annotation = annotation as? MyAnnotation {
      if let view = view as? MyMKAnnotationView {
        view.myMarker = annotation.myMarker
      }
    }
    return view
  }

Now in didSelectAnnotationView, retrieve the data you set when you created the annotation:

  func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
    if let view = view as? MyMKAnnotationView {
      if let marker = view.myMarker {
        toggleMarkerStatistics()  // hide or unhide the view
        // do something with your data
      }
    }
  }

Note:
I tried to copy and simplify this from my code, which actually tries to support both Apple and Google maps, so hopefully I don't have any typo's, but I think is a good representation of the steps I take.

A few more things to note:

  1. I think you must provide a title for the annotaion
  2. I think you must set the view's canShowCallout to false

I think both of these requirements can be found in the documentation, but I don't have a pointer to this right now.

nPn
  • 16,254
  • 9
  • 35
  • 58
  • This did work for me. Turns out though, what I wanted was a container view on top of the map with an embed segue. Thanks for your help @nPn ! – petfreshman Sep 19 '15 at 02:42