Search code examples
iosswiftuitableviewuistoryboardseguereloaddata

How to show the data in UITableView when dismissing modal view


I need help. My Recipe app has a main viewController with two UITableView (ingredientTableView and directionTableView). Each is populate from two modal view controllers by 'segue'.

The data are storage in the ingredient/direction array of new recipe, but the UITableView not display the text when dismissing the modal view.

This is the UIStoryboard image

The 'Save' UIBarButton code of newRecipeController:

    // MARK: - IBActions
extension AddNewRecipeViewController {

    // MARK: - Add Ingredient
    @IBAction func saveIngredient(_ segue: UIStoryboardSegue)
    {
        guard let addIngredientModalViewController = segue.source as? AddIngredientModalViewController,
            let ingredient = addIngredientModalViewController.ingredient else
        {
            return
        }

        // add the new ingredient to the ingredients array
        ingredients.append(ingredient)

        // update the tableview
        let indexPath = IndexPath(row: ingredients.count - 1, section: 0)
        ingredientTableView.insertRows(at: [indexPath], with: .automatic)
    }

    @IBAction func cancelAddIngredient(_ segue: UIStoryboardSegue)
    {
        dismiss(animated: true, completion: nil)
    }

This is the prepare for segue code of a modal view:

    // MARK: - Segue AddIngredient
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
    if segue.identifier == "SaveIngredient",
        let ingredientName = fieldAddNameIngredient.text,
        let ingredientValue = fieldValueOfIngredient.text
    {
        ingredient = IngredientModel(titleIngredientRecipe: ingredientName, subtitleIngredientRecipe: ingredientValue)
    }
}

Solution

  • We need to make sure your segues are working correctly. You need to ctrl+drag from the "add" button of the main tableViewController to the other view controller and make this a "push" segue.

    Then, ctrl+drag from the "save" button on the addNewRecipeViewController to the small exit icon just above the view controller. This will allow you to set up an unwind segue (which rolls back to the main view controller).

    Now you need to set up prepareForSegue() in the addNewRecipeViewController which gets the data ready to send back, then set up an unwind segue function in the main tableViewController to receive the data, update your array with the data and reload the tableView.

    First, in the addNewRecipeViewController. What you have should work. The important thing is that you set the view controller variable 'ingredient`, as this can then be passed back to the first view controller.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SaveIngredient",
            let ingredientName = fieldAddNameIngredient.text,
            let ingredientValue = fieldValueOfIngredient.text
        {
            ingredient = IngredientModel(titleIngredientRecipe: ingredientName, subtitleIngredientRecipe: ingredientValue)
        }
    }
    

    Then, in the main tableViewController we write the function that will receive data from the unwind segue.

    @IBAction func unwind(sender: UIStoryboardSegue) {
        if let sourceViewController = sender.source as? AddNewIngredientViewController, let ingredient = sourceViewController.ingredient {
            // Now ingredient holds the new data, so use it as you wish. This is an example:
            myIngredients.append(ingredient)
            tableView.reloadData()
        }
    }
    

    This way, you can pass whatever data you need back to the original tableViewController. I’m not quite sure how your custom classes are set up (Ingredient, Recipe etc) but as long as the second (data entry) view controller has a variable of the right type to store the data, it can be accessed like this in the first (master) view controller.

    Here is a tutorial on passing data in an unwind segue.


    Update:

    I have looked at the source code - the problem was not providing an unwind segue identifier in Storyboard identity inspector. There were also a few minor changes to tableView delegate code (checking tableView identity with === instead of ==).

    Image below show where to provide this identifier - this needs to match the check for the identifier in the unwind method.

    Unwind segue at bottom of scene in Storyboard

    Identifier for unwind segues