User95797654974
User95797654974

Reputation: 624

Updating a MKMapView based on transitions between UIViewControllers

I am building a map application similar to Apple Maps. Basically a half height sheet over a full screen map.

How shall I structure and detect transitions between view controllers on the sheet to update the map accordingly.

For example, let's say I have a Welcome VC and a Nearby Bus Stops VC. When the user goes from Welcome VC to Nearby Bus Stops VC, I want to add new bus stop annotations on the map. When the user go back to the Welcome VC from the Nearby Bus Stops VC, remove the annotations.

At the moment, I have a bunch of if-else statements which are not scalable as more view controllers are added and different possible combinations of transitions between view controllers are now possible in my app.

extension MainViewController: SheetControllerDelegate {
    func didChangeViewInSheet(from previousVC: UIViewController, to currentVC: UIViewController) {
        print("Changing from \(previousVC) to \(currentVC)")
        
        if currentVC is NearbyBusStopsVC && previousVC is WelcomeVC {
            addBusStopAnnotations()
        } else if previousVC is NearbyBusStopsVC && currentVC is WelcomeVC {

                removeBusStopAnnotations()

            //More code to run during this transition of view controllers in the sheet
        }
    }
}

Implementation of my SheetControllerDelegate

protocol SheetControllerDelegate: AnyObject {
    func didChangeViewInWelcomeSheet(from previousVC: UIViewController, to currentVC: UIViewController)
}

class SheetController {
    static let shared = SheetController()
    
    weak var delegate: SheetControllerDelegate? = nil
    
    private var secondLastVC: UIViewController? = nil
    
    //The stack of view controllers currently held in the sheet. Only the top most view controller visible to user. Very similar to push and pop behaviour
    var viewControllers: [UIViewController] = [] {
        willSet {
            secondLastVC = viewControllers.last
        }
        
        didSet {
            guard let topMostViewController = viewControllers.last else { return }
            guard let secondLastViewController = secondLastVC else { return }
            delegate?.didChangeViewInWelcomeSheet(from: secondLastViewController, to: topMostViewController)
        }
    }
    
    func present(_ viewController: UIViewController) {
        viewController.modalPresentationStyle = .overCurrentContext
        viewController.modalTransitionStyle = .coverVertical
        
        guard let lastVC = viewControllers.last else { return }
        
        lastVC.present(viewController, animated: true)
        viewControllers.append(viewController)
    }
    
    func dismiss(_ onCompletion: (() -> Void)? = nil) {
        viewControllers.removeLast()
        guard let lastVC = viewControllers.last else { return }
        lastVC.dismiss(animated: true) {
            onCompletion?()
        }
    }
}

Upvotes: 0

Views: 35

Answers (0)

Related Questions