3

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)
    }
}
cbuchart
  • 10,847
  • 9
  • 53
  • 93
Davide
  • 61
  • 1
  • 9
  • Your `saveIngredient()` function takes a segue as an argument (which it shouldn’t do as it is a button), but you never call it with a segue, so the `segue.source` is probably nil and the data never gets added to the table view due to the `guard` statement. Also, you don’t seem to have a reference to the main `tableView`. If you are dismissing the modal view and not using a segue, then `prepareForSegue()` will not be called. You might need to find the main `tableView` from the modal view with something like `self.presentingViewController()` then append to the table from that. – Chris Jun 03 '18 at 10:02
  • Also, are you storing all of the ingredients in an array in the main table view controller? – Chris Jun 03 '18 at 10:08
  • @Chris thx for your attention. The ingredients are storing in an array into principal array 'NewRecipe'. When I save the newRecipe the detailController load all ingredients. – Davide Jun 03 '18 at 10:13
  • @Chris, I try to follow your suggestion... but I'm new in Swift, I have more to learn again... – Davide Jun 03 '18 at 10:15
  • Looking at your storyboard, you might just need an unwind segue to send the data back to main view controller, then use `prepareForSegue()`. I’m not at my computer now but I’ll have a look at this later. – Chris Jun 03 '18 at 10:15
  • @Chris, ok, I try to use your suggestion. Thx a lot!!! – Davide Jun 03 '18 at 10:16
  • I have submitted an answer a I hope this is what you need! – Chris Jun 03 '18 at 12:12

1 Answers1

1

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

Chris
  • 4,009
  • 3
  • 21
  • 52
  • Thx Chris. I have try to modify with your example... nothing, not works. In detailController the ingredients are loaded but not in newRecipeController... I will try again with another solution. – Davide Jun 03 '18 at 12:47
  • The error disappear after correct with: 'ingredients.append(senderIngredientVC.ingredient)'. Without senderIngredientVC appear the error above... – Davide Jun 03 '18 at 12:53
  • I’d be happy to have a look at the XCode project file if you like? – Chris Jun 03 '18 at 13:06
  • Thanks I’ll have a look – Chris Jun 03 '18 at 13:29
  • @Davide - I have fixed it! I'll share the project back via DropBox - I have added comments and will update my answer. – Chris Jun 03 '18 at 15:14
  • Thank you so much Chris, I'm curios to have a look the fix! – Davide Jun 03 '18 at 15:26
  • Here is the DropBox link to the project: https://www.dropbox.com/sh/2gsa2helr8qymvl/AAC4Ws7m3m43VPBQ2amL8TQja?dl=0 – Chris Jun 03 '18 at 15:31
  • The ingredients now appear in list. There is some problem with the directionTableView as new directions would not appear after adding, but they would be there if you went back into that recipe, so the data is being saved. Nice app! – Chris Jun 03 '18 at 15:32
  • @Davide - My comments in your source code are all prefixed with `// CHRIS` – Chris Jun 03 '18 at 15:44
  • Great!!! Now is works! I'll try to fix the problem with directions now... Thank you so much!!! – Davide Jun 03 '18 at 16:04
  • @Davide - My pleasure! It’s a nice looking app.i hope the comments I have added make sense and are helpful. For your security, I will now delete the project from my DropBox. – Chris Jun 03 '18 at 16:05
  • As a final comment, you might see that the unwind method names and segue identifiers are different from the screenshot - I changed them as I was working. You can use whatever you want, but for anyone else reading this, the principles of the answer still apply. – Chris Jun 03 '18 at 16:07
  • Yes, I understand. I'm not delete your comment in my version for future needs! – Davide Jun 03 '18 at 16:11
  • @Davide If my answer was helpful, please consider marking it as accepted. Also, let me know if I can help other ways. I will keep working on the `directionTableView`! – Chris Jun 03 '18 at 16:30