help me!

Hello



I make recipe apps. I configured my pickerView and gave it Recipe name. What I want, is by clicking on my "Button", it's having the Recipe written on my "TextView" on another ViewController.


A little help will be cool


thank you


google traduction

Answered by Claude31 in 419333022

You said: this line destVC.Lavue = choix[name] ?? "" doesn't wor, an error message is displayed

Which error ?

Take care: selectedRow is in Int, so you need to find the name associated in choix[selectedRow]


How have you defined the class View2G (what I called RecipeViewController)?

Should have a property

var recipeText : String?          // LaVue is not a meaningful name, I propose you recipeText instead


The 2 var LeChoix and choix are different: one holds the list of recipes (array), the other the texts for recipes (dictionary).

You should also give meaningful names (as recipesDict), which start with lowerCase (Swift convention) (leChoix)

And you can initialize the dictionary at declaration or in viewDidload, that's the same.


You should have something like this:


in first ViewController,

var leChoix = ["Cake","Muffins"] // it's the name of the product for my pickerView 
var recipesDict : [String:String] = [:]     // That will hold the texts for recipês themselves


in viewDidload

recipesDict["Cake"] = "Take 200g of flour, 4 eggs…"     // Take care of uppercase in keys
recipesDict["Muffins"] = "150g Butter…"

Note: this could also be done instead at declaration:

var recipesDict : [String:String] = ["cake":"Take 200g of flour, 4 eggs…", "Muffins": "150g Butter…"]


Now in prepare


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

          if segue.identifier == "GoToRecipe" {
               if let destVC = segue.destination as? RecipeViewController {     // Maybe you named it View2G ; if so as? View2G
                    let selected = choixGouter.selectedRow(inComponent: 0
                    if selected >= 0 && selected < leChoix.count {     // Should always be true except if click out of bounds of picker
                         let recipeName = leChoix[selected]     // theTextYouSelectedInPicker, for instance "Cake"
                         destVC.recipeText = recipesDict[recipeName] ?? ""
                    }
               }
          }
     }

Some picker functions are wrong.

Should be

func numberOfComponents(in pickerView: UIPickerView) -> Int{
        return 1
    }

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
        return leChoix.count // NOT  choix.count, normally the same, but you never know
    }
    
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
        return leChoix[row]     // OK, in lowercase
    }

You should show some code, on both the originating controller with PickerView and destination in the other controller.


So you should do:

- create a segue between the originating controller and the destination controller

- give an identifier to the segue: GoToRecipe for instance

I assume the destination controller (where recipes are detailed) is a subclass of UIViewController, for instance declared as:

class RecipeViewController: UIViewController {


- in the destination controller, create a property:

class RecipeViewController: UIViewController {
    var recipeText : String?


- in the IBAction of the button, call

     @IBAction func theAction(_ sender: UIButton) {
          performSegue(withIdentifier: "GoToRecipe", sender: sender)
     }



- in the originating controller, have a prepare for segue wheere you pass the text

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
          if segue.identifier == "GoToRecipe" {
               if let destVC = segue.destination as? RecipeViewController {
                    destVC.recipeText = theTextYouSelectedInPicker
               }
          }
     }


- Then in viewDidLoad of RecipeViewController, feed the textView IBOutlet with recipeText.


If that is OK, don't forget to close the thread.

Otherwise, please explain what you don't understand.


PS: Are you from Orly near Paris ?

it's not really that, but I feel that we are approaching the solution.


the code seems correct to me with one exception:

when i select the name of the "product" like for example a "cake" in my pickerview, when i click on "button" i can see the recipe i wrote in my original viewController.

I have many "Product name" to put in my pickerView,

so many recipes to write in my textView.

I know I have to use the "if ... else" conditions to write my recipes one by one but I don't know where the code is placed.


ps: sorry I translate my questions on google translation, I hope it's understandable

and yes i'm from Orly near Paris, you know that city?

I do not understand what you want:


when i select the name of the "product" like for example a "cake" in my pickerview, when i click on "button" i can see the recipe i wrote in my original viewController.

So, you select only one product in picker to display in destin,ation ?

I have many "Product name" to put in my pickerView,

Yes, but you select only one, isn't it ?

so many recipes to write in my textView.

If you select a single product, you have a single recipe.


Where are those recipes stored ? In an array ? Or better in a dictionary ?

Could be like that in first ViewController,

var recipesDict : [String:String] = [:]

in viewDidload

recipesDict["cake"] = "Take 200g of flour, 4 eggs…"

And the same for each recipe.


Then in prepare


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

          if segue.identifier == "GoToRecipe" {
               if let destVC = segue.destination as? RecipeViewController {
                    let name = pickerView.selectedRow(inComponent: 0)     // theTextYouSelectedInPicker
                    destVC.recipeText = recipesDict[name] ?? ""
               }
          }
     }

doesn't work


I'll show you what I wrote :

var LeChoix = ["Cake","Muffins"] // it's the name of the product for my pickerView

but you tell my write

var choix : [String:String] = [:]


and now i have the 2 Variable

var choix : [String:String] = [:]
var LeChoix = ["Cake","Muffins"] // it's the name of the product for my pickerView



in my viewDidLoad

choix["cake"] = "500g farine..."


I wrote the functions for my pickerView

func numberOfComponents(in pickerView: UIPickerView) -> Int{
        return 1
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
        return choix.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
        return LeChoix[row]
    }


and now i wrote for my second viewController TextView (name View2G)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
            if segue.identifier == "GoToRecipe" {
                 if let destVC = segue.destination as? View2G {
                      let name = choixGouter.selectedRow(inComponent: 0)     // theTextYouSelectedInPicker
                    destVC.Lavue = choix[name] ?? ""
                 }
            }
       }


this line destVC.Lavue = choix[name] ?? "" doesn't wor, an error message is displayed

Accepted Answer

You said: this line destVC.Lavue = choix[name] ?? "" doesn't wor, an error message is displayed

Which error ?

Take care: selectedRow is in Int, so you need to find the name associated in choix[selectedRow]


How have you defined the class View2G (what I called RecipeViewController)?

Should have a property

var recipeText : String?          // LaVue is not a meaningful name, I propose you recipeText instead


The 2 var LeChoix and choix are different: one holds the list of recipes (array), the other the texts for recipes (dictionary).

You should also give meaningful names (as recipesDict), which start with lowerCase (Swift convention) (leChoix)

And you can initialize the dictionary at declaration or in viewDidload, that's the same.


You should have something like this:


in first ViewController,

var leChoix = ["Cake","Muffins"] // it's the name of the product for my pickerView 
var recipesDict : [String:String] = [:]     // That will hold the texts for recipês themselves


in viewDidload

recipesDict["Cake"] = "Take 200g of flour, 4 eggs…"     // Take care of uppercase in keys
recipesDict["Muffins"] = "150g Butter…"

Note: this could also be done instead at declaration:

var recipesDict : [String:String] = ["cake":"Take 200g of flour, 4 eggs…", "Muffins": "150g Butter…"]


Now in prepare


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

          if segue.identifier == "GoToRecipe" {
               if let destVC = segue.destination as? RecipeViewController {     // Maybe you named it View2G ; if so as? View2G
                    let selected = choixGouter.selectedRow(inComponent: 0
                    if selected >= 0 && selected < leChoix.count {     // Should always be true except if click out of bounds of picker
                         let recipeName = leChoix[selected]     // theTextYouSelectedInPicker, for instance "Cake"
                         destVC.recipeText = recipesDict[recipeName] ?? ""
                    }
               }
          }
     }

Some picker functions are wrong.

Should be

func numberOfComponents(in pickerView: UIPickerView) -> Int{
        return 1
    }

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
        return leChoix.count // NOT  choix.count, normally the same, but you never know
    }
    
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
        return leChoix[row]     // OK, in lowercase
    }

Thank you very much for your precious help, and thank you for your patience, thanks to you i will be able to advance to create my app.

really a big thank you

help me!
 
 
Q