affichage/instanciation UIViewController depuis cellule UITableView (segue storyboard)
Bonjour,
J'aimerais comprendre et arriver à ouvrir une UIViewController depuis le clic d'une cellule UITableView, en utilisant le storyboard.
En gros, j'ai une UITableView avec du contenu (cellule sans label juste la cellule et du texte) et au clic de cette derrière je souhaiterais afficher/instancier une UIViewController en récupérant le bon index précédemment sélectionné.
Donc, j'ai bien utilisé une segue (showItemSegue) entre UITableView(cellule) et mon UIViewController(View) (dans storyboard mes vues sont bien linker à des class)
dans le code de ma UITableView tout me semble bon (?):
import UIKit
class TableViewController: UITableViewController
{
var table = String()
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.dataTable.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = UITableViewCell(style: .default, reuseIdentifier: "cellule")
cell.textLabel?.text = self.dataTable[indexPath.row]
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if (segue.identifier == "showItemSegue")
{
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let itemViewController: ItemViewController = storyBoard.instantiateViewController(withIdentifier: "showItemSegue") as! ItemViewController
self.navigationController?.pushViewController(itemViewController, animated: true)
itemViewController = ItemViewController()
itemViewController.table = self.table
}
}
}
et dans mon UIViewController, rien de spécial pour le moment, juste des tests d'affichagent des données récupérées depuis la segue de ma UITabelView
Mais pour le moment rien ne fonctionne, c'est à dire qu'aucun UIViewController ne s'affiche... Je ne pense pas qu'un "push" soit nécessaire ? le storyboard via mon navigationController devrais s'en chargé avec la segue surtout, non ?
Merci à tous
Edit:
Bon, je viens de testé ce ci :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!)! as UITableViewCell
self.data = currentCell.textLabel!.text!
let vc = ItemViewController()
present(self.vc, animated: true, completion: nil)
}
J'ai une vue qui s'ouvre mais le background est black, alors que je ne définit pas cette couleur dans mon projet (storyboard ou via du code)
et mes données passées via la segue (en console) ne s'affiche pas.
Réponses
Bonjour,
Tu as juste oublier d'implementer la méthode qui permet de detecter le click sur la cell, rajoute ce code :
alors avec ce code :
et dans la méthode prepare for segue :
j'ai une erreur de compilation :
je viens de vérifier dans mon storyboard le nom est bien "showItemSegue"... je comprends pas du coup
salut,
lol ben j'essais de tout viré (pour suivre tes conseils) mais pas facile, suis un adepte du code... je trouve ça plus "maitrise"
en tout cas je te le redis encore ! mais merci beaucoup pour ton aide !
je post la dernière version de ce que j'ai fait histoire d'être clair :
mon storyboard complet :
très bien
De mémoire on évite de créer un segue dans le Storyboard depuis une cellule vers un autre UIViewController, cela risque de bypasser le prepareForSegue:sender: Mais on lie plutôt les 2 UIViewControllers entre eux.
Quand crées un segue et l'utilises, pas besoin de faire de créer le prochain UIViewController dans prepareForSegue:sender:.
Donc tout ça :
let itemViewController = self.storyboard!.instantiateViewController(withIdentifier: "showItemSegue") as! ItemViewController
let navController = UINavigationController(rootViewController: itemViewController)
present(navController, animated:true, completion: nil)
comme je disais (je crois) si je fais ça :
J'ai une nouvelle vue qui s'affiche, mais, elle est noir et vide, donc je ne vois pas d'ou elle provient, puisque dans mon code ou storyboard, à aucun moment je donne un background black et pas de bouton "back" (navigation)
En tout cas c'est pas une instance de la mienne...
mais juste pour les tests j'ai créer une pop up et là tout fonctionne bien, c'est à dire que via cette méthode la pop up s'affiche bien avec mes données sélectionnées.
ça je le sent pas, ça me fait tout planté... En plus, il est déjà dans le storyboard, bref je verrais demain, là , je comprends pas trop.
Edit:
j'ai aussi oublié de précisez que mon point d'entrée est le navigationController, car je veux une UIViewControler (ou ce trouve mes boutons) qui mène (au clic) à ma UITableView (là tout fonctionne bien, données affichées) et au clic de la cellule ouverture d'une UIViewController pour le détail des data
Il faut comprendre la différence entre un segue et l'ancienne méthode plus manuelle.
Quand tu veux présenter un nouvel écran, voici les 3 étapes :
• Créer le ViewController
• Faire différents paramétrages sur ce dernier.
• Aller à ce view controller.
Ce que te permet le segue (et les storyboards)
La création n'est pas à faire par code.
Aller à ce view controller n'est pas à faire par code.
Le segue sait qui est lié, et il a en propriété destinationViewController qui est celui que tu avais besoin de créer précédemment.
Les paramétrages sont à faire dans le prepareForSegue:sender:. Là , une fois que tu as identifié ton segue (via sa propriété identifier), tu lui configure le prochain view controller.
En général :
La manière dont il est présenté, c'est dans les propriété du segue dans le Storyboard : Push, Show, etc, il saura lui-même que faire.
Qu'est-ce que ça apporte concrètement : Pourquoi utiliser un Storyboard et les segues qui vont avec ?
Déjà , tu sais à quoi ressembles l'applications. Tu as rapidement une vue d'ensembles des cheminements, des users-stories.
Tu évites moult initWithNibName (ou assimilés) pour la première étape.
La manière dont il est présenté est automatisée. Avant, il fallait se dire que si mon ViewController de départ avait une NavigationBar, il fallait faire un Push, alors que maintenant, il se sait déjà .
Tu peux continuer de faire toi-même des alloc/init d'un ViewController, son paramétrage, et sa présentation, mais c'est en plus rare, à la marge.
Pour en revenir à ton précédent code :
let itemViewController = ItemViewController()
present(itemViewController, animated:true, completion: nil)
Là , tu as créé un nouveau ItemViewController, mais clairement pas celui qui est dans un Xib ou dans ton Storyboard. Il n'y a pas eu d'appel (caché) à initWitCoder/awakeFromNib.
oui tu as raison je n'instanciais pas le bon objet, si j'ai bien compris maintenant je devrais faire ceci :
Mais, là encore ou je comprends toujours pas et ou ça plante (erreur de segue non reconnu, comme plus haut) c'est donc ici :
là , cette fois c'est le bon objet qui est pointé... Donc, d'après moi, j'ai un soucis dans mon storyboard, ayant tout vérifié et n'ayant pas grand chose je sèche .
Il ne trouve pas de segue avec comme identifiant showItemSegue. Donc il est très probable que ton identifiant ne corresponde pas ou n'est pas renseigné. Si tu cliques sur la liaison entre ton premier controller et celui vers lequel tu veux aller dans ton storyboard, dans le panneau à droite tu dois renseigner l'identifiant du segue. À priori, puisque dans ton code c'est showItemSegue, tu dois le nommer lui aussi showItemSegue. Les deux doivent être identiques.
salut et merci,
le soucis est qu'ils correspondent bien.
je drag de la cellule de ma tableView et je drop sur la view de mon ViewController, ensuite je donne comme id "showItemSegue"
ViewController(ItemViewController) du storyboard est bien associé à ma classe swift ItemViewController qui lui correspond
donc, je vois plus trop là ,
J'ai oublié de préciser précédemment.
Du coup, le prepareForSegue:sender: ne fait que préparer le terrain.
Il faut que tu dises à ton code :
Fais le segue avec tel identifiant, via la méthode performSegue(withIdentifier identifier:sender:)
Avant d'aller à l'écran suivant, prepareForSegue:sender: est appelé.
Si tu as des paramétrages à faire, c'est là qu'il faut le faire.
Code non-certifié (car je ne code pas en Swift)
Mais cela ne résoudra pas le problème de segue avec identifiant mauvais.
On est bien d'accord :
Le segue, c'est la p'tite flèche qui lie 2 UIViewControllers.
Ce dernier a son propre identifiant.
Un UIViewController a aussi un identifiant.
Vu ton code, j'ai l'impression que tu mets l'identifiant du prochain ViewController et pas du segue.
Et bien pour la flèche, elle part du TableViewController (de ça cellule pour être précis) et va sur la View de mon UIViewController, la segue qui les relies à bien pour identifier "showItemSegue"
Je ne peut de toute façon pas mettre une segue sur une vue sans "la flèche"
une "flèche" = segue
cellule View
UItableView
> UIVewController
identifier : "showItemSegue"
donc, je ne vois pas trop... Les "identifier" son pour moi les segues ? et les ID storyboard je ne m'en sert pas.
je vais tout supprimer et refaire un nouveau projet, au cas ou j'aurais fait une bêtise dans le storyboard ...
Edit :
pour plus de clarté :
pour l'erreur à la compilation, je n'ai plus d'erreur d'identifier à présent, mais un plantage sans 'info' juste un soucis de "mauvaise instruction thread"
nouveau code :
Tu t'obstines à créer ton viewcontroller. et à le présenter toi-même ! ARRàŠTE!
D'ailleurs instantiateViewController(withIdentifier: "showItemSegue"), c'est l'identifier du segue que tu mets, alors qu'il attend l'un d'une ViewController !
Logique :
À faire dans le STORYBOARD:
Créer un Segue reliant deux ViewControllers.
Donner un identifiant à ce segue
Modifier sa présentation si nécessaire.
À faire dans le CODE :
Quand tu veux changer d'écran, appeler au bon moment performSegue(withIdentifier:sender:)
Cela va appeler tout seul prepare(for segue:sender:).
Là , donner les paramètres qu'il faut au prochain viewcontroller.
Soit c'est l'heure tardive, j'explique mal ou y'a une coquille dans mes explications précédentes, soit tu ne lis que la moitié de ce qui t'intéresse.
Et à tord, je pensais que la méthode instanciait le bon automatiquement ! Donc, oui je n'avais juste pas pigé cette méthode...
la, j'ai pigé !
Je verrais tout ça demain.
Dure journée, ceci explique cela aussi ...
Merci,
Bonjour
Je commence avec le storyboard :
salut
je regarde tout ça merci,
Le code :
Et, c'est tous.
Projet complet ci-joint
juste une petite question comment tu as fait pour nommé tes objet dans le storyboard ?
je veux parlé de ta tableView et de ItemViewController.
Dans le cartouche du dessus on vois leur nom : Tables (tableViewController) et Item View Controller (tableViewController) ?
Sinon, je voulais te dires que si j'avais plusieurs segue ("J'ai fait deux segues du UINavigationController") s'étais pour ma fameuse histoire de point d'entrée sur une ViewController puis une tableViewController (et non comme ton exemple directement start l'application sur une tableViewController) Je ne sais pas faire autrement...
Je refais tout pour bien comprendre là ! Beaucoup de chose était confuse pour moi, oui...
Edit: et merci pour le Zip ! je vais quand même le refaire à la mano pour mieux comprendre.
Merci beaucoup ! ! !
Tu ouvres le projet que j'ai mis en pièce-jointe et tu l'examines :-*
"Tables" vient du fait que j'ai nommé le navigationItem du TableViewController. Dans le Document Outline, tu vois un bouton qui contient une flèche vers la gauche ; cliques là et tu verras dans le Attributes Inspector, que Title contient Tables.
"Item View Controller" vient du nom de la classe du contrôleur, automatiquement fait par Xcode. Ce n'est pas visible à runtime.
Si tu mettais deux segues d'un UINavigationController, c'est en disant que tu veuilles faire deux choses au même temps ou que tu veuilles avoir une choix, mais on ne peut pas le faire.
Bien sûr que tu puisses avoir plusieurs segues qui proviennent d'un viewController d'autre type mais, UINavigationController, c'est spécial .
Je n'attendais que tu fasses autrement 8--)
coucou,
bon j'ai bien étudier ton code et je pense en avoir pigé l'essentielle !
Cependant j'ai une question, concernant mon idée de démarrer mon application sur une UIVIewController (avec un navigationController de linker sur lui) et que cette vue via des boutons (coder et donc pas dans le storyboard) je veux aller sur une UITableViewController,
tu m'avais déconseiller (comme j'avais fait) de tirer 2 segues du navigationController, une vers le point d'entrée UIViewController et l'autre vers la UITableViewController.
Mais du coup comment le faire ? (storyboard)
PS:
je vais aussi commencer à m'intéresser à UICollectionView, mais pour mon projet je ne le ferais pour les boutons (tables)
Dans ton image du storyboard, tu montres deux segues de la UINavigationController. Comme je t'ai déjà dit, la UINavigationController fait une pile ou stack ; du coup, on ne peut pas avoir qu'un segue comme rootViewController.
Alors, pour faire ce que tu veux, il ne faut que remplacer la première UITableViewController avec une UIViewController avec tes "boutons".
Mais là , je te déconseillerais fortement. Tu as fait un projet d'essaie pour voir ce qui se passe avec les boutons si tu fais pivoter le simulateur (menu Hardware | RotateLeft/Right) ?
Sans autolayout (possible mais pénible en code) les boutons ne suivent pas la rotation et ne changeront pas leurs agencement.
Si tu ne veux pas utiliser la UICollectionView, tu a déjà la UITableView, qui fait, comme je t'ai montré, un rang par table name
C'est facile avec UICollectionViewController :
Et, dans le storyboard :