Search code examples
iosswiftmapboxmglmapview

When are swift functions called in programs where no function call is visible?


The example below is taken from Mapbox, and shows how to mark a location on a map with an annotation. I understand that viewDidLoad is called when the app starts and thats what runs everything inside the viewDidLoad function.

I don't understand how the last two functions in this program are called(which both seem to have the name mapView). I see no reference to them inside viewDidLoad

import Mapbox

class ViewController: UIViewController, MGLMapViewDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()

    let mapView = MGLMapView(frame: view.bounds)
    mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    // Set the map’s center coordinate and zoom level.
    mapView.setCenter(CLLocationCoordinate2D(latitude: 40.7326808, longitude: -73.9843407), zoomLevel: 12, animated: false)
    view.addSubview(mapView)

    // Set the delegate property of our map view to `self` after instantiating it.
    mapView.delegate = self

    // Declare the marker `hello` and set its coordinates, title, and subtitle.
    let hello = MGLPointAnnotation()
    hello.coordinate = CLLocationCoordinate2D(latitude: 40.7326808, longitude: -73.9843407)
    hello.title = "Hello world!"
    hello.subtitle = "Welcome to my marker"

    // Add marker `hello` to the map.
    mapView.addAnnotation(hello)
  }

  // Use the default marker. See also: our view annotation or custom marker examples.
  func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
    return nil
  }

  // Allow callout view to appear when an annotation is tapped.
  func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
    return true
  }
}

Solution

  • These are delegate methods declared by protocol called MGLMapViewDelegate which is implemented to your class

    class ViewController: UIViewController, MGLMapViewDelegate { ... }
    

    By setting delegate of some object as your controller (= self) like you did with your MGLMapView in viewDidLoad

    mapView.delegate = self
    

    you're saying that when some method is called on mapView's delegate, method which you've implemented like mapView(_:viewFor:) -> MGLAnnotationView? will be called.


    Anyway, your mapView should be instance variable, otherwise you lost reference for it

    class ViewController: UIViewController, MGLMapViewDelegate {
    
        var mapView: MGLMapView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            mapView = MGLMapView(frame: view.bounds)
            ...
        }
    }