Passer une info dans container

Bonsoir tous le monde,


 


je revient je cherche a passer une info de un UITableViewController vers UITableViewController qui contient un container.


 


j'ai déjà  cela



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let cell = sender as? UITableViewCell {
if let indexPath = self.tableView.indexPath(for: cell) {
let selectedPerson = searchResults[indexPath.row]["idsite"].stringValue

let personViewController:InfoSearchTableViewController = segue.destination as! InfoSearchTableViewController
personViewController.TabInfos = [selectedPerson]
}
}
}
}

Ce que je cherche c'est de faire cela



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail1" {
if let cell = sender as? UITableViewCell {
if let indexPath = self.tableView.indexPath(for: cell) {
let selectedPerson = searchResults[indexPath.row]["idsite"].stringValue

let personViewController:NewstTableViewController = segue.destination as! NewstTableViewController
personViewController.TabInfos = [selectedPerson]
}
}
}
}

j'ai tous fait mais j'ai des  erreur ou id est vide.


 


Merci de votre aide.


 


 


 


 


 


 


«1

Réponses

  • Commence par expliquer quelle est la grosse différence entre les deux.



    let personViewController:NewstTableViewController = segue.destination as! NewstTableViewController

    vs



    let personViewController:InfoSearchTableViewController = segue.destination as! InfoSearchTableViewController

    Et donner les erreurs aussi, ça peut être très pratique. Car là , j'avoue que je n'ai aucune idée de quoi ça ne marche pas, je ne sais pas si les connexions sur le Storyboard ont été faites au niveau du segue, son nommage, etc.

  • NewstTableViewController ou l'on trouve une partie fixe avec table view cell.


    InfoSearchTableViewController c'est le résultat d'une recherche.


     


    On clic InfoSearchTableViewController sur son choix et on passe au détaille ou il y une partie fixe et une partie qui bouge (table view cell) qui ce trouve dans un container (la partie qui bouge).


    Cela fonction mais j'ai besoin  de passer l'id du produit.


    Tous cela dans le même storyboard.


     


    Oui j'ai déjà  demander cela, mais j'en est deux a passer comme info, dans deux class différente.


    Sa met une erreur.



    Invalid redeclaration
    of 'prepare(for:sender:)'

    Je comprend pas.


     


    Merci a vous,

  • J'ai l'impression que tu as 2 fois la fonction "prepare(for:sender:)"..


     


    Met tout le code de ta classe en entier, ça sera plus simple pour visualiser, parce que comme ça, on ne connait pas le contexte de ton code..


  • easydeasyd Membre
    février 2017 modifié #6

    Voilà  mon code



    import UIKit
    import SwiftyJSON

    class SearchResultsTableViewController: UITableViewController {

    @IBOutlet weak var menuButton:UIBarButtonItem!

    var TabInfos:[[String:Any]] = []

    var searchResults = [JSON]() {
    didSet {
    tableView.reloadData()
    }
    }

    var validatedText: String {
    return searchController.searchBar.text!.replacingOccurrences(of: " ", with: "").lowercased()
    }

    let searchController = UISearchController(searchResultsController: nil)
    let requestManager = RequestManager()

    override func viewDidLoad() {
    super.viewDidLoad()

    searchController.searchBar.delegate = self
    searchController.dimsBackgroundDuringPresentation = false
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.searchBar.placeholder = "Search..."
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar
    searchController.searchBar.sizeToFit()

    NotificationCenter.default.addObserver(self, selector: #selector(SearchResultsTableViewController.updateSearchResults), name: NSNotification.Name(rawValue: "searchResultsUpdated"), object: nil)

    if revealViewController() != nil {
    menuButton.target = revealViewController()
    menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
    view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    }

    func updateSearchResults() {
    searchResults = requestManager.searchResults
    }

    override func numberOfSections(in tableView: UITableView) -> Int {

    return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return searchResults.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)

    cell.textLabel?.text = searchResults[indexPath.row]["nom_prduit"].stringValue
    cell.detailTextLabel?.text = searchResults[indexPath.row]["id_produit"].stringValue

    if indexPath.row == searchResults.count - 10 {
    if requestManager.hasMore {
    requestManager.getNextPage(validatedText)
    }
    }

    return cell
    }

    deinit {
    NotificationCenter.default.removeObserver(self)
    }
    }


    extension SearchResultsTableViewController: UISearchBarDelegate {
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {

    requestManager.resetSearch()
    updateSearchResults()
    requestManager.search(validatedText)
    }

    //cela fontionne id_produit passe bien
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetail" {
    if let cell = sender as? UITableViewCell {
    if let indexPath = self.tableView.indexPath(for: cell) {
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue

    let personViewController:InfoSearchTableViewController = segue.destination as! InfoSearchTableViewController
    personViewController.TabInfos = [selectedPerson]
    }
    }
    }
    }

    //cela fontionne pas id_produi vide
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetail1" {
    if let cell = sender as? UITableViewCell {
    if let indexPath = self.tableView.indexPath(for: cell) {
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue

    let personViewController:NewstTableViewController = segue.destination as! NewstTableViewController
    personViewController.TabInfos = [selectedPerson]
    }
    }
    }
    }
    }


  • On est bien d'accord que tu as une seule fois override func prepare(for segue: UIStoryboardSegue, sender: Any?) { ?


  • GoodGoodGoodGood Membre
    février 2017 modifié #8

    Bonjour easyd,


     


    Effectivement tu as 2 fois la même méthode ce qui n'est pas possible, d'ou le message du compilateur qui te dit que tu ne peu pas redeclarer la fonction prépar. 


  • InsouInsou Membre
    février 2017 modifié #9

    Comme l'ont dit les autres, t'as 2 fois la même méthode..


     


    Mais en fait, t'essaie de faire ouvrir à  ton "segue" (showDetail) 2 view différentes ? Si c'est le cas, ça ne fonctionnera jamais !


     


    Fait plutôt un switch sur l'identifiant de ton segue..


     


    Un truc du style :



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

    print(segue.identifier)

    switch(segue.identifier){

    case "showDetail":
    if let cell = sender as? UITableViewCell {
    if let indexPath = self.tableView.indexPath(for: cell) {
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue

    let personViewController:InfoSearchTableViewController = segue.destination as! InfoSearchTableViewController
    personViewController.TabInfos = [selectedPerson]
    }
    }
    break;

    case "identifiantDeTonAutreSegue":
    // ton code pour l'autre vue
    ​ break;
    }
    }

  • Merci,


     


    j'ai modifier et j'ai une erreur



    case "showDetail": //erreur là 
    if let cell = sender as? UITableViewCell {
    if let indexPath = self.tableView.indexPath(for: cell) {
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue

    let personViewController:InfoSearchTableViewController = segue.destination as! InfoSearchTableViewController
    personViewController.TabInfos = [selectedPerson]
    }
    }
    break;

    case "showDetail1": //erreur là 
    if let cell = sender as? UITableViewCell {
    if let indexPath = self.tableView.indexPath(for: cell) {
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue

    let personViewController:NewstTableViewController = segue.destination as! NewstTableViewController
    personViewController.TabInfos = [selectedPerson]
    }
    }

    break;
    }
    }

    il me dit 



    Expression pattern of type 'String' cannot match values of type 'String?'
  • Joanna CarterJoanna Carter Membre, Modérateur
    février 2017 modifié #12

    Ouah ! Quelle pagaille !!!


     


    Il faut mieux connaà®tre Swift  ;)



    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
    guard let cell = sender as? UITableViewCell,
    let indexPath = self.tableView.indexPath(for: cell),
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue else
    {
    return
    }

    if segue.identifier == "showDetail",
    let personViewController = segue.destination as? InfoSearchTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    return
    }

    if segue.identifier == "showDetail1",
    let personViewController = segue.destination as? NewstTableViewController
    {
    personViewController.TabInfos = [selectedPerson]
    }
    }

    Mais je ne comprends pas pourquoi tu passes selectedPerson dans un array  :/


  • j'ai des erreurs



    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
    guard let cell = sender as? UITableViewCell,
    let indexPath = self.tableView.indexPath(for: cell),
    let selectedPerson = searchResults[indexPath.row]["id_produit"].stringValue else
    {
    return
    }

    if let segue.identifier == "showDetail", // Variable binding in a condition requires an initializer
    let personViewController = segue.destination as? InfoSearchTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    return
    }

    if let segue.identifier == "showDetail1", // Initializer for conditional binding must have Optional type, not 'String'
    let personViewController = segue.destination as? NewstTableViewController
    {
    personViewController.TabInfos = [selectedPerson]
    }
    }

    Merci de ton aide,

  • Joanna CarterJoanna Carter Membre, Modérateur

    J'ai modifié mon code


  • easydeasyd Membre
    février 2017 modifié #15
    Merci encore de ton aide, mais j'ai un problème dans InfoSearchTableViewController j'ai bien mon ID.

    Et dans NewstTableViewController et vide rien.

     

    J'ai même modifier le code pour n'utiliser l'un ou autre, même chose dans l'un j'ai le ID et dans l'autre vide.

     

    NewstTableViewController est un CONTAINER  (UITableViewController)

     

     


    InfoSearchTableViewController (UIViewController)

     


    J'ai constater quelque chose c'est que le code est executer jusqu'a 



    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
    guard let cell = sender as? UITableViewCell,
    let indexPath = self.tableView.indexPath(for: cell),
    let selectedPerson = searchResults[indexPath.row]["id_produit"].string else
    {
    return
    }

    if segue.identifier == "showDetail22",
    let personViewController = segue.destination as? InfoSearchTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    print("TabInfosddd2222", personViewController.TabInfos)

    return
    }

    Puis le suite ne execute pas j'ai mis un print pour tester



    if segue.identifier == "showDetail2",
    let personViewController = segue.destination as? NewstTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    print("TabInfosddd", personViewController.TabInfos)
    }
    }

    Merci de votre aide


  • T'as bien créer un segue qui s'appel "showDetail2" dans ton main.storyboard ?


     


    Met ton code entre balise "code", c'est plus lisible parce que là  ça fait brouillon et ça donne pas envie de répondre ;)


  • JérémyJérémy Membre
    février 2017 modifié #17


    T'as bien créer un segue qui s'appel "showDetail2" dans ton main.storyboard ?




    Il n'y aurait pas un moyen de créer une Enum contenant tous les noms des segues que nous pourrions utiliser directement dans XIB et dans les différentes UIViewController ? Une faute de frappe est si vite arrivée... De plus, si un jour pour X raison le nom devait changer (que nous mettrions dans un attribut code de l'Enum), nous aurions uniquement à  le modifier à  un seul endroit.



    enum SegueDictionary {
    case fromHomeToUsersList, fromHomeToUserDetails, fromUsersListToUserDetails

    var all: [SegueDictionary] {
    return [fromHomeToUsersList,fromHomeToUserDetails,fromUsersListToUserDetails]
    }

    var code: String {
    switch self {
    case fromHomeToUsersList:
    return "fromHomeToUsersList"
    case fromHomeToUserDetails:
    return "fromHomeToUserDetails"
    case fromUsersListToUserDetails:
    return "fromUsersListToUserDetails"
    }
    }
    }


    // Dans le VC
    if let segue.identifier == SegueDictionary.fromHomeToUsersList.code {...}

    Reste à  voir si il est possible d'adapter XIB pour qu'il nous propose une liste (la liste de l'enum) plutôt que de taper l'identifier à  la mano.


  • Perso, ça dépasse un peu mon domaine de compétence là  ^^


    J'laisserai donc quelqu'un de plus calé que moi pour y répondre :p


     


    Après si c'est juste pour éviter une erreur de frappe et éviter de le changer à  plusieurs endroits, j'trouve que c'est en faire beaucoup pour pas grand chose..


    Perso, j'ai jamais eu besoin de recharger le nom d'un segue, une fois qu'il est mis, j'y touche plus et j'ai pas de cas concret en tête qui me ferait faire changer le nom d'un segue régulièrement (si quelqu'un à  un exemple..)


    Puis l'erreur sur le nom du segue est assez explicite pour se rendre compte qu'on à  fait une faute de frappe (ça m'est déjà  arrivé, ça se corrige en 2 sec :p)


  • Puis l'erreur sur le nom du segue est assez explicite pour se rendre compte qu'on à  fait une faute de frappe (ça m'est déjà  arrivé, ça se corrige en 2 sec :P)



     


    Faut il voir le problème avant que l'application soit en prod. ::)



  • Faut il voir le problème avant que l'application soit en prod. ::)




     


    Bah j'espère que tu teste un minimum ton application avant de la mettre en prod  xd



  • Faut il voir le problème avant que l'application soit en prod. ::)




    Je sais que pour certains, Compiler c'est livrerTester c'est douter, mais bon :p


     


    J'ai vu un projet/script qui fait l'inverse. Il lit les Storyboard et génère des consts équivalentes.

  • JérémyJérémy Membre
    février 2017 modifié #22


    Je sais que pour certains, Compiler c'est livrerTester c'est douter, mais bon :P




     


    :D ;)


     


    Non mais suivant la taille de ton projet, tu ne peux pas forcément tout tester dans tous les sens à  chaque livraison... Mon idée était de garantir la conformité des codes entre ton ViewController et XIB. Dans ton ViewController, il suffit que tu glisses une coquille dans le code de ton Segue (V1.4 de ton app), alors que tu ne devais pas le modifier, pour que ça ne fonctionne plus.


  • Joanna CarterJoanna Carter Membre, Modérateur

    Ou, on a toujours les oe“uvres de notre cher AliGator https://github.com/AliSoftware/SwiftGen#uistoryboard




  • :D ;)


     


    Non mais suivant la taille de ton projet, tu ne peux pas forcément tout tester dans tous les sens à  chaque livraison... Mon idée était de garantir la conformité des codes entre ton ViewController et XIB. Dans ton ViewController, il suffit que tu glisses une coquille dans le code de ton Segue (V1.4 de ton app), alors que tu ne devais pas le modifier, pour que ça ne fonctionne plus.




     


    Tests Unitaires, Tests d'UI.
    BluePill (à  ne pas confondre avec une autre pilule de la même couleur) de LinkedIn semble donner quelques aides là -dessus.

  • Joanna CarterJoanna Carter Membre, Modérateur

    Si on a un projet complexe, on est obligé de faire les tests unitaires ; sinon on est vachement fou/folle  :-*


  • Joanna CarterJoanna Carter Membre, Modérateur


     


    Merci encore de ton aide, mais j'ai un problème dans InfoSearchTableViewController j'ai bien mon ID.

    Et dans NewstTableViewController et vide rien.

     

    J'ai même modifier le code pour n'utiliser l'un ou autre, même chose dans l'un j'ai le ID et dans l'autre vide.

     

    NewstTableViewController est un CONTAINER  (UITableViewController)

     

     


    InfoSearchTableViewController (UIViewController)

     


    J'ai constater quelque chose c'est que le code est executer jusqu'a 



    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
    guard let cell = sender as? UITableViewCell,
    let indexPath = self.tableView.indexPath(for: cell),
    let selectedPerson = searchResults[indexPath.row]["id_produit"].string else
    {
    return
    }

    if segue.identifier == "showDetail22",
    let personViewController = segue.destination as? InfoSearchTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    print("TabInfosddd2222", personViewController.TabInfos)

    return
    }

    Puis le suite ne execute pas j'ai mis un print pour tester



    if segue.identifier == "showDetail2",
    let personViewController = segue.destination as? NewstTableViewController
    {
    personViewController.TabInfos = [selectedPerson]

    print("TabInfosddd", personViewController.TabInfos)
    }
    }

    Merci de votre aide


     




     


    Bien sur, le code pour "showDetail2" n'exécutera au même temps que ce pour "showDetail22" à  cause de return à  la fin du code pour "showDetail22".


     


    Il n'est pas possible de préparer pour deux segues au même temps car il n'est pas possible de montrer deux vues au même temps.


     


    Comme dit les autres, tu as bien un segue avec le nom "showDetail2" dans le storyboard ?


     


    Et, pour ta santé mentale, utilises les noms plus significatifs pour les segues, comme "showSearchController" et "showNewstController".


     


    Et pour InfoSearchTableViewController, s'il n'est pas un UITableViewController, le nommer plutôt InfoSearchViewController.

  • JérémyJérémy Membre
    février 2017 modifié #27


    Tests Unitaires, Tests d'UI.




     


     




    Si on a un projet complexe, on est obligé de faire les tests unitaires ; sinon on est vachement fou/folle  :-*




     


    Je suis d'accord avec vous. Cependant, ce n'est pas parce que nous avons des tests qui déterminent si nous avons choppé le VIH (pour avoir des traitements qui te maintiennent plus ou moins en vie) que nous ne devons nous affranchir d'une éventuelle protection... Si ?


     


    Okay c'est une image tordue mais l'idée est là . :D


  • @JérémySwiftGen (plus de 3000 stars dans GitHub) fait ce que tu veux.


  • Je revient vers vous,


     


    J'ai une question je peux stocker une variable dans la mémoire et l'utiliser quant je veux ???


     


    Cela est possible en PHP, coté serveur bien sûr comme $_session.


     


    ::)

  • Joanna CarterJoanna Carter Membre, Modérateur

    On peut toujours utiliser les globales mais c'est pas souvent conseillé. Qu'est-ce que tu veux faire avec ?


  • je voudrais stocker l'id du produit pour l'utiliser après dans la vue NewstTableViewController .


    je comprend pas cela devrais fonctionner de passer l'id d'une vue a une autre.


     


    On ne peux le faire que pour une seul vue pas plusieurs.

Connectez-vous ou Inscrivez-vous pour répondre.