Silver Challenge: User’s Location

// added “NSLocationWhenInUseUsageDescription$(PRODUCT_NAME) location use.” in the Info.plist

// it only works with a real iOS device connected

import UIKit
import MapKit

class MapViewController: UIViewController, MKMapViewDelegate {

// MARK: - Properties

var mapView: MKMapView!
var locationManager = CLLocationManager()                                                          // Silver Challenge

// MARK: - UIViewController Method

override func loadView() {
    mapView = MKMapView()
    view = mapView
    mapView.delegate = self                                                                        // Silver Challenge
    
    let segmentedControl = UISegmentedControl(items: ["Standard", "Hybrid", "Satellite"])
    segmentedControl.backgroundColor = UIColor.white.withAlphaComponent(0.5)
    segmentedControl.selectedSegmentIndex = 0
    
    segmentedControl.addTarget(self, action: #selector(MapViewController.mapTypeChanged(_:)), for: .valueChanged)
    
    segmentedControl.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(segmentedControl)
    
    let topConstraint = segmentedControl.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 8)
    let margins = view.layoutMarginsGuide
    let leadingConstraint = segmentedControl.leadingAnchor.constraint(equalTo: margins.leadingAnchor)
    let trailingConstraint = segmentedControl.trailingAnchor.constraint(equalTo: margins.trailingAnchor)

    topConstraint.isActive = true
    leadingConstraint.isActive = true
    trailingConstraint.isActive = true
    
    /* -------------------- my add for the Silver Challenge: create a button programmatically --------------------- */
    
    let button = UIButton(type: .system)
    button.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
    button.setTitle("Show Location", for: .normal)
    button.setTitleColor(UIColor.white, for: .normal)
    button.layer.cornerRadius = 5
    button.addTarget(self, action: #selector(MapViewController.buttonAction(sender:)), for: .touchUpInside)
    button.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(button)
    
    let bottomConstraintBtn = button.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor, constant: -10)
    let marginsBtn = view.layoutMarginsGuide
    let leadingConstraintBtn = button.leadingAnchor.constraint(equalTo: marginsBtn.leadingAnchor)
    let trailingConstraintBtn = button.trailingAnchor.constraint(equalTo: marginsBtn.trailingAnchor)
    
    bottomConstraintBtn.isActive = true
    leadingConstraintBtn.isActive = true
    trailingConstraintBtn.isActive = true
    
    /* ------------------------------------------------------------------------------------------------------------ */
    
}

override func viewDidLoad() {
    super.viewDidLoad()
    print("MapViewController loaded its view.")
}

// MARK: - Helper Methods

func mapTypeChanged(_ segControl: UISegmentedControl) {
    switch segControl.selectedSegmentIndex {
    case 0:
        mapView.mapType = .standard
    case 1:
        mapView.mapType = .hybrid
    case 2:
        mapView.mapType = .satellite
    default:
        break }
}

func buttonAction(sender: UIButton!) {                                                             // Silver Challenge
    locationManager.requestWhenInUseAuthorization()
    mapView.showsUserLocation = !mapView.showsUserLocation           // instead of: "mapView.showsUserLocation = true"
    // the statement below can replace the entire method "func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation)", eventhough the effect will be different
    /* mapView.userTrackingMode = .followWithHeading */ // works fine only the first time the "Show Location" button gets pressed, then the heading/compass capabilities disappear
    if mapView.showsUserLocation == true {

        sender.setTitle("Hide Location", for: .normal)
    }
    else {
        sender.setTitle("Show Location", for: .normal)
    }
}

// MARK: - MKMapViewDelegate Method

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {                       // Silver Challenge
    let region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 500, 500)
    mapView.setRegion(region, animated: true)
}

}