Bronze Challenge: StackViews in Worldtrotter

Our task was to update Worldtrotter with StackViews. I guess the authors meant to update the individual views. In case of Conversion one can delete all the constraints of the individual objects and then add a StackView and place all objects inside, set margins, top and bottom and use autolayout.

In case of the Map the StackView has to be added programmatically. The main change here is to make the stackview the actual view. The difficult part is to get the segmentcontrol overlay the map. I searched and found a solution (Keith Harrison https://useyourloaf.com/blog/stack-view-background-color/). Here is the whole code. Not shown is the UIView extension file, which has to be added as a separate swift file and can be found in the tutorial.

class MapViewController: UIViewController, MKMapViewDelegate {
    
    // Variable declarations
    var mapView: MKMapView!
    var stackView:UIStackView!
    var innerStackView: UIStackView!
    var segmentStack: UIStackView!
    
    override func loadView() {
        
        // Creating an instance of a stackview and make it the main view
        stackView = UIStackView()
        stackView.alignment = .fill
        view = stackView
        
        // Creating another instance of a stackview for the map
        innerStackView = UIStackView()
        innerStackView.axis = .vertical
        innerStackView.spacing = 5
        innerStackView.alignment = .fill
        
        mapView = MKMapView()
        mapView.delegate = self
        innerStackView.insertArrangedSubview(mapView, at: 0)
        
        // Top Buttons for changing Map View
        let standardString = NSLocalizedString("Standard", comment: "Standard map view")
        let hybridString = NSLocalizedString("Hybrid", comment: "Hybrid map view")
        let satelliteString = NSLocalizedString("Satellite", comment: "Satellite map view")
        
        let segmentedControl = UISegmentedControl(items: [standardString, hybridString, satelliteString])
        segmentedControl.backgroundColor = UIColor.white.withAlphaComponent(0.5)
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.addTarget(self, action: #selector(MapViewController.mapTypeChanged(_:)), for: .valueChanged)
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        
        segmentStack = UIStackView()
        segmentStack.axis = .horizontal
        segmentStack.alignment = .top
        segmentStack.distribution = .equalCentering
        segmentStack.layoutMargins = UIEdgeInsets(top: 30, left: 10, bottom: 0, right: 10)
        segmentStack.isLayoutMarginsRelativeArrangement = true
        segmentStack.insertArrangedSubview(segmentedControl, at: 0)
        
        stackView.insertArrangedSubview(innerStackView, at: 0)
    }
    
    // Function to create a foreground
    func pinForeground(_ view: UIView, to stView: UIStackView) {
        view.translatesAutoresizingMaskIntoConstraints = false
        stView.addSubview(view)
        view.pin(to: stView)
    }
    
    // Function to set the map view type
    func mapTypeChanged(_ segControl: UISegmentedControl) {
        switch segControl.selectedSegmentIndex {
        case 0:
            mapView.mapType = .standard
        case 1:
            mapView.mapType = .hybrid
        case 2:
            mapView.mapType = .satellite
        default:
            break }
    }
        
    // Function when view is called
    override func viewDidLoad() {
        super.viewDidLoad()
        
        pinForeground(segmentStack, to: innerStackView)
        print("MapViewController loaded its view.")
    }
}