Octa CZO
Octa CZO

Reputation: 51

I can't execute functions from a ViewController in an different one

Can someone help me execute functions from one VC in another VC. The function from the first VC needs to be executed once I press a button in the second VC. Im trying with "viewcontroller().function()" function but it's not working properly, printing and basic stuff works but when it comes to stuff like drawing direction it's not working.

The function that draws directions is:

func directionToPin() {

    guard let currentPlacemark = currentPlacemark else {
        print("Error, the current Placemark is: \(self.currentPlacemark)")
        return
    }

    let directionRequest = MKDirections.Request()
    let destinationPlacemark = MKPlacemark(placemark: currentPlacemark)

    directionRequest.source = MKMapItem.forCurrentLocation()
    directionRequest.destination = MKMapItem(placemark: destinationPlacemark)
    directionRequest.transportType = .walking

    //calculate route
    let directions = MKDirections(request: directionRequest)
    directions.calculate{ (directionsResponse, error) in

        guard let directionsResponse = directionsResponse else {
            if let error = error {
                print("error getting directions: \(error.localizedDescription)")
            }
            return
         }

        let route = directionsResponse.routes[0]

        if self.drawedDriection == false {
            self.drawedDriection = true

            if self.didSelectAnnotation == true {
                self.mapView.addOverlay(route.polyline, level: .aboveRoads)self.navigationBarController.directionButtonOutlet.setImage(UIImage(named: "navigationBarDirectionButtonRed")?.withRenderingMode(.alwaysOriginal), for: .normal)
                        self.mapView.setRegion(MKCoordinateRegion(routeRect), animated: true)
                    }
                } else {
                    self.drawedDriection = false
                    self.mapView.removeOverlays(self.mapView.overlays)
                    if self.didSelectAnnotation == true {
                        self.navigationBarController.directionButtonOutlet.setImage(UIImage(named: "navigationBarDirectionButtonBlue")?.withRenderingMode(.alwaysOriginal), for: .normal)
                    } else {
                        self.navigationBarController.directionButtonOutlet.setImage(UIImage(named: "navigationBarDirectionButtonGray")?.withRenderingMode(.alwaysOriginal), for: .normal)
                    }
                }
            }
        }

I'm calling the function in the second VC once I press a button:

@IBAction func directionButton(_ sender: Any) {
    MapViewController().directionToPin()
} 

When I run the app and press the button the currentPlacemark is nil, if I run the same function via a button in my first VC (the VC with the directionToPin function inside)

here is my repo if you need it: https://github.com/octavi42/xCodeMapsApp

Thanks!

Upvotes: 0

Views: 93

Answers (1)

Sarath Kumar Ganesan
Sarath Kumar Ganesan

Reputation: 203

I think that you need to use Protocols and Delegates to achieve what you desire.

@IBAction func directionButton(_ sender: Any) {
    MapViewController().directionToPin()
} 

In the above code snippet, you are instantiating a new instance of MapViewController which upon initialization resets currentPlacemark and hence you've encountered nil.

My suggestion is to create a new protocol to communicate from MapViewController to CardViewController just like this

Add these in MapViewController.swift

protocol MapNavigationDelegate: AnyObject {
    func didTapDirectionButton()
}

class MapViewController: UIViewController {
    // .... Some code ....

    override func viewDidLoad() {
        // . .... Some more code .......
        navigationBarController.mapNavigationDelegate = self
    }
}

extension MapViewController: MapNavigationDelegate {
    func didTapDirectionButton() {
        self.directionToPin()
    }
}

Add these in CardViewController.swift

class CardViewController: UIView {
    // .... Some Code ....
    weak var mapNavigationDelegate: MapNavigationDelegate!

    @IBAction func directionButton(_ sender: Any) {
        self.mapNavigationDelegate.didTapDirectionButton()
    }
}

Upvotes: 2

Related Questions