简体   繁体   中英

Transitioning from a modally presented view controller to a view controller in a tab bar controller

I have been struggling with the following and would be grateful for some help.

When the 'FINISH' button is pressed on the 'Add Location' scene and some code runs. After the code completes, then one of the scenes titled 'On the Map' should show( whichever you pressed + on).

The 'On The Map' titled scenes are nested in navigation controllers and tab bar controllers.

When you press + the 'Find Location' scene shows. Press 'FIND LOCATION' then 'Add Location' scene shows.

The question I have is how to transition from the Add Location scene to the appropriate 'On the Map' scene?

在此输入图像描述

This is the code that transitions from the map or table view scene to the 'Find Location' scene.

    @IBAction func addLocation(_ sender: Any) {
//        if Constants.CurrentUser.objectId == "" {
//            displayFindLocationVC()
//        } else {
            let title = "Student has a location"
            let message = "\(Constants.LoggedInUser.firstName) \(Constants.LoggedInUser.lastName) has posted a student location. Would you like to overwrite the existing location?"
            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Overwrite", style: .default   ) {
                action in
                self.displayFindLocationVC()
            })
            alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
            present(alert, animated: true, completion: (displayFindLocationVC))
        //}
    }

    func displayFindLocationVC() {
        let findLocationVC = storyboard?.instantiateViewController(withIdentifier: "FindLocation") as! FindLocationViewController
        present(findLocationVC, animated: true, completion: nil)
    }

Thank you for the help.

Instead of presenting the Add Location view controller directly, embed it in a navigation controller which you can access using the navigationController property in the Add Location view controller. Then you can dismiss the navigation controller to reveal the tab bar controller.

// AddLocationViewController.swift

@IBAction func didTouchUpInsideFinishButton() {

    // ...

    navigationController?.dismiss(animated: true, completion: nil)
}

故事板截图

Stefan, I recommend using a delegate, so you can tell the 'Find Location' and 'Add Location' scenes where to report back to.

First define a protocol in your map view controller class, something like this:

protocol OnTheMapDelegate {
    func didChooseLocation(location:CLLocation)
}

class OnTheMapViewController:UIViewController {
    override func viewDidLoad() {
        // etc...
    }
}

Then make your OnTheMapViewController conform to this protocol like so:

class OnTheMapViewController:UIViewController, OnTheMapDelegate {
    override func viewDidLoad() {
        // etc...
    }
    func didChooseLocation(location:CLLocation) {
        // Do something with location object returned from other scenes here.
    }
}

You will now need to give the other scenes a reference back to the OnTheMapViewController so that when the user has selected their new location we can pass it back.

In the top of your FindLocationViewController and AddLocationViewController classes add a variable to store this reference

class FindLocationViewController:UIViewController {
    var delegate:OnTheMapDelegate?
    override func viewDidLoad() {
        // etc...
    }
}

class AddLocationViewController:UIViewController {
    var delegate:OnTheMapDelegate?
    override func viewDidLoad() {
        // etc...
    }
}

Next inside the AddLocationViewController scene, once the user has selected a new location, pass it back using the delegate like this:

class AddLocationViewController:UIViewController {
    var delegate:OnTheMapDelegate?
    override func viewDidLoad() {
        // etc...
    }

    func userSavedNewLocation(loc:CLLocation) {
        if let del = self.delegate {
            del.didChooseLocation(location:loc)
        }
    }
}

All thats left to do is make sure that when you create a new instance of either the FindLocationViewController or AddLocationViewController scene you set the delegate variable correctly.

Using your code the first example of this will look like this in your map view controller:

func displayFindLocationVC() {
    let findLocationVC = storyboard?.instantiateViewController(withIdentifier: "FindLocation") as! FindLocationViewController
    findLocationVC.delegate = self
    present(findLocationVC, animated: true, completion: nil)
}

The second time you need to pass it will be when you initialise the Add Location scene, I'm assuming this is inside of the Find Location scene, so it will look something like this:

func displayAddLocationVC() {
    let addLocationVC = storyboard?.instantiateViewController(withIdentifier: "AddLocation") as! AddLocationViewController
    if let del = self.delegate {
        addLocationVC.delegate = del
    }
    present(addLocationVC, animated: true, completion: nil)
}

The only thing i didn't mention here is that you will also want to dismiss each of the modal view controllers in order to show the OnTheMapViewController underneath, to do this, you just need to call this somewhere in each class, probably when you are done with that vc:

self.dismiss(animated: true, completion: nil)

This is un-tested code please let me know how you get on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM