1
votes

Comment ouvrir un contrôleur de navigation avec le titre de la cellule sélectionnée

Je voudrais qu'un contrôleur de navigation s'ouvre lorsqu'une cellule de tableau est sélectionnée. Le contrôleur de navigation doit avoir le titre du texte contenu dans la cellule sélectionnée.

Je pense que je suis très proche de mon code, mais je n'arrive pas à comprendre ce que je fais mal.

Rien ne s'ouvre lorsque je sélectionne une cellule du tableau.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


    let cellIdentifier: String = "stockCell"
    let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
    myCell.textLabel?.textAlignment = .center

    // Get the stock to be shown
    let item: StockModel = feedItems[indexPath.row] as! StockModel
    // Configure our cell title made up of name and price

    let titleStr = [item.customer].compactMap { $0 }.joined(separator: "-")

    print(titleStr)
    // Get references to labels of cell
    myCell.textLabel!.text = titleStr

    let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "detailController")
    controller.title = titleStr
    navigationController?.pushViewController(controller, animated: true)

}

NOUVELLE MISE À JOUR:

CE QUI SUIT MAINTENANT FONCTIONNE:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        // Retrieve cell
        let cellIdentifier: String = "stockCell"
        let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
        myCell.textLabel?.textAlignment = .center
        myCell.textLabel?.font = .boldSystemFont(ofSize: 18)
        // Get the stock to be shown
        let item: StockModel = feedItems[indexPath.row] as! StockModel
        // Configure our cell title made up of name and price


        let titleStr = [item.customer].compactMap { $0 }.joined(separator: "-")


        print(titleStr)
        // Get references to labels of cell
        myCell.textLabel!.text = titleStr

        return myCell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let item: StockModel = feedItems[indexPath.row] as! StockModel
        let titleStr = [item.customer].compactMap { $0 }.joined(separator: "-")

        print(titleStr)

    }

     func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "customerDetails" {

        let destinationVC = segue.destination as UIViewController
        let cellIdentifier: String = "stockCell"
        let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
        destinationVC.navigationItem.title = myCell.textLabel!.text
        }
    }

}

Mais j'ai besoin que le contrôleur de vue se présente comme un style de storyboard Show Detail, où le detailController recouvre le FirstViewController.

Où vous ne pouvez pas revenir en arrière.


4 Réponses :


1
votes

Vérifiez si le segue est connecté dans le fichier main.storyboard. Si tel est le cas, vérifiez que l'identifiant correspond à celui du code. Si cela ne fonctionne pas, c'est peut-être parce que vous créez une nouvelle cellule dans prepareForSegue et que pour résoudre ce problème, vous devez créer une variable globale pour chaque cellule. Si tout cela ne fonctionne pas, dites-moi. Pouvez-vous joindre le fichier main.storyboard.


1 commentaires

Je ne sais pas comment créer une variable globale, mais tout le reste est correct. Je pense que je passe la valeur de la cellule (texte dans la cellule) de manière incorrecte



1
votes

Dans ce cas, il est préférable de simplement pousser le contrôleur de vue par programmation. Un exemple complet extrêmement simple ressemblerait à ceci:

var nextScreenTitle: String?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "customerDetails" {
        let destinationVC = segue.destination as UIViewController
        destinationVC.title = nextScreenTitle
    }
}

Donc, en utilisant navigationController? .PushViewController (controller, animated: true) est une méthode qui affichera un nouveau contrôleur de vue avec animation de droite à gauche.

Un titre est simplement défini directement sur le contrôleur de vue qui peut être créé à partir du storyboard en utilisant UIStoryboard (nom: "Main", bundle: nil). instantiateViewController (withIdentifier: "anyIdentifierISetInStoryboard") .

Cela suppose que ce contrôleur de vue est déjà sur le contrôleur de navigation.

Si vous avez vraiment besoin de le faire avec des segues alors vous devez appeler manuellement le segue à l'aide d'identificateurs. Vous envoyez également votre titre en tant que paramètre expéditeur .

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let item: StockModel = feedItems[indexPath.row] as! StockModel
    let titleStr = [item.customer].compactMap { $0 }.joined(separator: "-")
    self.nextScreenTitle = titleStr
    self.performSegue(withIdentifier: "customerDetails", sender: self)
}

Dans votre cas, probablement quelque chose comme:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "customerDetails" {
        let destinationVC = segue.destination as UIViewController
        destinationVC.title = sender as? String
    }
}

Et puis utilisation:

self.performSegue(withIdentifier: "customerDetails", sender: titles[indexPath.row])


18 commentaires

Je n'obtiens aucune erreur mais le titre n'apparaît tout simplement pas dans le titre du contrôleur de navigation


@RelsonJames Mes excuses. La méthode prepareForSegue a été renommée dans le dernier Swift. Veuillez vérifier ma réponse mise à jour. Vous devez utiliser override func prepare (pour segue: UIStoryboardSegue, sender: Any?) {


Il n'apparaît toujours pas, est-ce que le texte de la cellule n'est pas transmis correctement?


@RelsonJames Il est possible que votre chaîne soit nil ou vide. Essayez de le confirmer. Je vous suggère de mettre un point d'arrêt à l'intérieur de prepare (for segue (vous appuyez à gauche du code sur une ligne et une puce bleue devrait apparaître). Lorsque vous exécutez votre projet, il doit s'arrêter à cette ligne et vous pouvez inspectez toutes les valeurs. De plus, vous pouvez à ce stade utiliser votre console (partie inférieure droite de Xcode) pour imprimer les valeurs auxquelles vous avez accès. Vous utilisez généralement "po" pour imprimer votre objet. Dans votre cas, essayez "po sender as? String" . Cela devrait vous donner la chaîne que vous avez créée. Si elle est nulle, vérifiez-la dans performSegue .


L'expéditeur: titleStr est correctement défini dans performSegue mais est nul dans destinationVC.tlte = sender comme? Chaîne


@RelsonJames cela semble un peu étrange. Vous l'avez inséré dans la méthode, non? expéditeur: titleStr . Si c'est le cas, j'aurai peut-être besoin de plus d'informations sur ce qui se passe. J'ai reproduit votre scénario et cela semble fonctionner pour moi. Il y a toujours un autre moyen cependant. Puisque votre cellule est sélectionnée, vous pouvez également recréer la chaîne dans votre méthode. Au lieu de indexPath , vous auriez besoin de tableView.indexPathForSelectedRow! . Ou ajoutez une autre propriété à laquelle vous définissez votre chaîne sur la cellule sélectionnée, puis utilisez-la pour préparer la séquence.


Juste pour clarifier ce que signifie l'insérer dans la méthode?


@RelsonJames juste pour confirmer que vous l'avez inséré comme dernier paramètre ici self.performSegue (withIdentifier: "customerDetails", sender: titleStr) . Que ce n'est pas par exemple self.performSegue (withIdentifier: "customerDetails", sender: nil)


@RelsonJames Y a-t-il une chance pour moi de jeter un coup d'œil sur le projet? Je crois que vous pouvez trouver mon e-mail dans mon profil.


J'ai en fait décidé de suivre vos conseils et d'essayer de ne pas utiliser de segues et de tout simplifier


Le problème que j'ai maintenant est que l'option de storyboard ne se charge pas et plante à la place l'application. Par option de story-board, j'entends utiliser UIStoryboard (nom: "Main", bundle: nil) .instantiateViewController (withIdentifier: "anyIdentifierISetInStoryboard")


La méthode programmatique fonctionne bien et le titre est passé correctement, mais je préférerais utiliser la méthode du storyboard car j'ai tout conçu là-bas


@RelsonJames Oui et bien je suis sûr que ce doit être un bogue idiot que vous n'introduisiez pas cette chaîne dans votre méthode, mais j'aurais besoin de regarder plus en profondeur ce qui se passe. J'ai cependant édité la réponse pour donner une autre solution. Essayez peut-être celui-là.


Je l'apprécie, une dernière chose lors de l'utilisation d'UIStoryboard (nom: "Main", bundle: nil) .instantiateViewController (withIdentifier: "anyIdentifierISetInStoryboard") l'application plante. Je dois utiliser la version storyboard et non l'approche programmatique. Pouvez-vous jeter un oeil?


@RelsonJames Que dit le journal des accidents? Il génère généralement quelque chose dans la console. Vous devez y insérer les identifiants appropriés. Le nom du storyboard doit également être correct. Vous devez donc vérifier que le storyboard "Main" est le même que le nom de fichier de votre storyboard et que "n'importe quelIdentifierISetInStoryboard" doit être égal à l'identifiant du contrôleur de vue que vous avez défini dans le storyboard; il se trouve sous "ID du Storyboard".


Oui, je me suis assuré que les deux étaient égaux, mais comment la valeur de la table est-elle transmise au contrôleur de storyboard si nous nous débarrassons de «let controller =»? Je suppose que nous n’avons pas raison parce que vous avez dit ou


@RelsonJames this segue.destination vous donne la référence à votre contrôleur de vue. C'est donc pareil.


J'ai posté une mise à jour, encore une fois j'apprécie vraiment votre aide. Cette fois, tout fonctionne correctement, sauf pour le contrôleur présentant un style Afficher les détails (où le contrôleur passe sur le contrôleur de vue qui le déclenche). Comment cela peut-il être fait? Je montre le code que j'utilise dans la mise à jour



1
votes

Vous devez utiliser variable dans deistinationVC puis dans ViewDidLoad utilisez "navigationItem.title"

Dans firstViewController strong >:

class secondViewcontroller : UIViewController{

  var navTitle = string()

  override func viewDidLoad() {

    navigationItem.title = navTitle

   }

Et SecondViewController :

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "customerDetails" {

    let destinationVC = segue.destination as UIViewController
    let cellIdentifier: String = "stockCell"
    let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
    destinationVC.navTitle = myCell.textLabel!.text
    }
}


2 commentaires

N'oubliez pas de définir "var navTitle = string ()" dans distinationVC


utilisez push pour naviguer >> laissez vc = storyboard? .instantiateViewController (withIdentifier: "customerDetails") as! customerDetailsVC. et >> vc.navTitle = titleStr et >> navigationController? .pushViewController (vc, animated: true)



1
votes

faites-le dans votre version de mise à jour

let controller = storyboard.instantiateviewcontroller(withIdentifier: "youridentifier") as? "name of your view controller"
navigationController?.present(controller, animated: true, completion: nil)


0 commentaires