Segue tra TableView e stati di un ViewController

Andremo veloci perché già hai in mano la maggior parte dei concetti per poter mettere in pratica il passaggio delle informazioni. Bisogna solo adattarlo ad un ambiente leggermente più complesso come quello delle tabelle. Quello che faremo, quindi, è creare una Tabella, selezionare un elemento e passare le informazioni di quell'elemento ad una View dei [...]

Torna a: Corso creare applicazioni per iOS con il linguaggio Swift > TableView, TabBar e CollectionView
  • Francesco

    Ciao Peppe,

    sto facendo un esercizo, ho creato una tabella tramite un array che prende i dati dal un file xml remoto e cliccando sulla riga porta a una ipotetica pagina dettagli. Tutto ok :-)

    ora ho notato che quando torno indietro o ritorno in altro modo alla tabella il processo di parsing riparte. (il parse e come il Tuo tutorial)

    alla scoperta di questa ultima lezione sugli stati ti volevo chiedere, come si fa per evitare questo? come posso sapere se il metodo viewdidload viene eseguito o no?

    Nel tutorial nel viewdidload viene richiamato :

    let bool = parser!.parse()
    print(“Parsing (bool)”)
    self.tableView.reloadData()

    ora dimmi se giusto visto che se ritorno indietro il viewCotroller tabella è gia in memoriaria devo fare in modo che non esegua questo comando e faccio leggere solo array oppure devo usare del codice nel metodo viewDidAppear?

    non riesco a capiere bene a livello logico e se ho scritto cavolate! Credo ci sia una sistema in quanto è inutile ogni volta eseguire i parse per non appesantire l’app e richiamre i dati inutilmente

    Grazie

    • Ciao Francesco,

      Se aggiungi un Navigation Controller e gestisci le transizione con lo Show Segue, non dovresti più avere questo tipo di problema in quanto il NC tiene in memoria i VC precedenti a quelli di destinazione e, di conseguenza, il ritorno indietro non causerà l’invocazione del viewDidLoad.

      In alternativa, un sistema per la gestione del parser è quello di utilizzare una classe Controller dove inserire i metodi di parsing. Così facendo puoi utilizzare un singleton o una static var che ti comunica quando il parsing è stato eseguito oppure no.

      Fammi sapere ;)

      • Francesco

        Ciao,
        io ho rifatto il tutorial del parse quello scritto da te sulle parse del feed del sito che prevede un navigator controller ma ho notato che viene fatto ogni volta che accedo alla tabella, ho provato a caricare la tabella disattivare la connessione e riaprire la tabella ma non appare nulla o bisogna fare in altro modo o mi perdo qualche passaggio

        Grazie

        • Ho scaricato il progetto, aggiunto un ViewController con segue di tipo Show e funziona tutto perfettamente lasciando il codice nel viewDidLoad.
          Quando torno indietro dal 2 VC non viene ricaricata la tabella perché il codice è nel viewDidLoad ;)

          • Francesco

            Ciao,

            scusami perchè allora se io tolgo la connessione dopo avere caricato la tebella essa non è più visibile quando torno indietro? scusa se ti faccio perdere tempo ma è solo per imparare :-)

            • Mmmh in che senso se togli la connessione?

              Comunque non ti preoccupare, sono qui apposta :P

            • Francesco

              allore io un VC con NV, clicco sul link e mi apre la tabella tramite un segue, poi cliccando su una riga della tabella vado in dettglio. a questo punto io ho notatato questo (ovviamente è un mio esperimento e ho fatto questo sistema che è il primo che mi è venuto in mente), metto in modalità aereo clicco indietro e mi compare nuovamente la tabella come dici tu, torno indietro ancora (VC del link) e riprovo a cliccare sul link e questa volta mi riporta alla tabella ma è bianca.

              è giusto così? cioè e normale che sia bianca o visto che ha il memoria la i dati mi dovrebbe fare vedere la tabella come quando ritorno indietro dalla pagina dettagli?

            • Si così è giusto, quell’applicazione non tiene conto della presenza o meno della connessione. Quindi senza connessione non funziona

            • Francesco

              scusa ma la tabella o meglio i dati non sono in memoria come quando torni indietro?

            • Da quello che ho capito hai 3 VC, il VC nel mezzo è quello con la tabella dove viene eseguito il parsing.

              Se torni indietro dalla tabella al primo VC in cui premi il link, questa viene eliminata dalla memoria e, se sei senza internet, al ritorno la vedrai bianca perché non verrà eseguito il parsing.

            • Francesco

              ah ok scusa ma tante nozioni e mi intrigo… faccio tanti esercizi come questo proprio per prendere dimestichezza… spero che pubblichi presto nuovei lezioni.

              Ti volevo chiedere se pensavate di fare tipo delle sezione o rubriche dove spiegate nel dettaglio tipo come utilizzare le scroll View , gallerie di immagine, gestire le date, interagire con il calendario e cose simili, credo siano utili per chi impare da zero in quanto sono cose che si utilizzano in quasi in tutte le applicazioni.

              come sempre grazie :-)

            • Si è già nel nostro intento! alcune delle cose da te richieste verranno già trattate nelle prossime settimane sul blog ;)

  • Alfonso

    Ciao Peppe,

    innanzitutto complimenti per il corso, davvero ben fatto :)

    Sto provando ad implementare la modifica al progetto (gestione di appuntamenti completati).

    Dato l’array di tipo Appuntamento:

    var appuntamenti: [Appuntamento] = [Appuntamento(nome: “Alfonso”), Appuntamento( nome: “Giuseppe”), Appuntamento(nome: “Simone”), Appuntamento(nome: “Aldo”)]

    override func viewDidLoad() {
    self.appuntamenti[0].completato = true
    super.viewDidLoad()
    self.myTable.delegate = self
    self.myTable.dataSource = self
    }

    calcolo il numero di righe da visualizzare in tabella considerando solo le entry che hanno la proprietà completato = false.

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    var contatore = 0
    for x in self.appuntamenti {
    if (!x.completato){
    contatore++
    }
    }
    return contatore
    }

    Il mio problema è con la cellForRowAtIndexPath poiché vorrei visualizzare solo le righe con completato = false (e solo per esse valorizzo il testo) ma comunque anche per le righe che devono essere ignorate mi viene visualizzata una cella.

    Inoltre, avendo calcolato il numero di righe in base agli appuntamenti non completati, ho una visualizzazione solo parziale della tabella:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(“myCell”, forIndexPath: indexPath)
    let appuntamento = self.appuntamenti[indexPath.row]
    if (!appuntamento.completato) {
    cell.textLabel?.text = self.appuntamenti[indexPath.row].nome!
    }
    return cell
    }

    So che questo codice è errato :) ma non posso restituire nil

    Come posso risolvere?

    Grazie mille

    • Ciao Alfonso,

      Se il tuo intento è quello di visualizzare solo gli utenti con status false, il mio consiglio è quello di creare una sorgente esclusiva per questi dati.
      Cioè invece di utilizzare un solo array, si crea un secondo array contenente solo gli oggetti con proprietà = false. Questo array infine si passa alla tabella.

      Il metodo che stavi utilizzando non va bene eprché la cellForRowAtIndexPath prende il numero di indice restituito dal metodo numberOfRowAtIndexPath. Quindi se la funzione ritorna 4 (perché il ciclo ha trovato 4 utenti con proprietà false) la cellForRowAtIndexPath dato che pescherà i dati dall’array di utenti (con tutti gli utenti) si arresterà al numero 4 e non prenderà in esame gli altri.

      Per questo motivo, prima di dare in pasto un array alla tabella è consigliato togliere gli elementi che non devono essere visualizzati.

      In alternativa puoi creare una tabella con due Section. Una per gli utenti TRUE e l’altra per i False. In questo caso puoi utilizzare un unico array.

      ——————

      In realtà puoi anche usare un solo array, solo che, all’interno della cellForRowAtIndexPath devi andare a ciclare nuovamente l’array di utenti per pescare quello con proprietà false, ma diventerebbe complicato in quanto ogni metodo viene eseguito una volta per riga. Quindi ad ogni riga dovresti ricordarti quello che ha fatto il cellForRowAtIndexPath precedente.

      • Alfonso

        Grazie mille,
        ho risolto con l’introduzione di un nuovo array contenente solo gli elementi da visualizzare

  • Salve, uno strano bug che non riesco a risolvere: dopo il run cliccando su un qualsiasi elemento della tabella mi porta al detailviecontroller due volte consecutive come se ce ne fossero due. E se faccio back lo devo ripetere due volte per tornare alla tabella. Ho creato un nuovo progetto da zero ma il bug è comunque presente. Anche nell’output invia due volte e questo capita solo dopo aver inserito il performsegue…
    Grazie per l’aiuto.

    • Ciao Angelo,

      Assicurati di non aver creato un segue che parte dalla Custom Prototype Cell verso il Detail View Controller. Il segue deve essere generale e quindi deve partire dal View Controller, se no, ti genera questo errore.

      • è quello di sicuro ;-) grazie

        • Non c’è di che ;)

          Giuseppe Sapienza
          xCoding.it | Sviluppa, Crea e codifica i tuoi sogni!

  • nickbonny

    Ciao peppe, sto cercando risolvere l’esercizio di modifica di un nome all’interno della lista con il metodo 2 (#2 Passaggio dell’indice). Non riesco però a passare al detailVC l’indice della tableView. Cioè io vorrei fare:

    – passare al detailVC il nome da modificare, let nome = (isSenderEmpty as! UITableViewCell).textLabel!.text!
    – passare al detailVC l’indice corrispondente a quella row della tabella, questo è il mio problema!! non so come fare
    – poi l’unwind prende il valore della textfield e lo sostituisce nell’array alla posizione corretta
    – infine faccio un reloadData() per aggiornare la tabella

    Grazie in anticipo

    • Ciao Nick,

      Per risolvere l’esercizio con il punto 2, devi creare una proprietà per la classe chiamata “indice_corrente” o qualcosa del genere (tipo Int). Nel metodo didSelectRowAtIndex salvi il valore della riga corrente in questa variabile. Poi esegui il segue dove passi il valore da modificare. Lo modifichi nel secondo VC e quando torni indietro, riprendi il valore di quella variabile “indice_corrente” e aggiorni l’array con il nuovo valore dato che conosci l’indice dell’elemento che era stato selezionato.

      Spero di essere stato chiaro

      • nickbonny

        Ok ma aspetta forse mi sono spiegato male..
        adesso stavo parlando di risolvere senza il didSelectRowAtIndex. cioè il mio problema è nel momento in cui passo le informazioni dal viewController al detailVC. Infatti non riesco a passare una costante int che sia l’indice della cella che voglio modificare.
        Cioè il testo lo passo così come hai fatto tu: let testo = (isSenderEmpty as! UITableViewCell).textLabel!.text!
        mentre l’indice come lo passo?

        • L’indice lo devi passare come ti ho spiegato nella risposta precedente. Senza utilizzare la indexPathForSelectedRow. Nel metodo didSelectRowAtIndex prendi il valore del parametro indexPath.row e lo salvi in una proprietà della classe TuaClasseViewController. Poi questo valore lo utilizzi quando fai l’unwind per modificare l’elemento.

  • Raoul Gioia

    Ciao Giuseppe, sono alle prese con ”l’esercizio da risolvere” (aggiunta della classe Appuntamento), ho implementato una mia soluzione
    che funziona ma nel far questo ho riscontrato una anomalia o presunta anomalia di cui non mi ero ancora accorto. Descrizione della situazione:
    La struttura è quella del progetto sviluppato nella lezione ”Segue tra TableView e stati di un ViewController”. L’anomalia è la seguente:
    quando premo il bottone (Conferma modifica) del ”DettaglioViewController” vengo riportato al primo ”ViewController” e chiamata la @IBAction unwind che ho implementato non una volta ma due volte perché? Nel mio codice la @IBAction si chiama ”unwindToHome”. Al
    suo interno c’e il guard sull’segue.identifier e poi il solito switch. Il bottone invece è collegato alla @IBAction attraverso l’exit del
    ”DettaglioViewController” e specificato un identifier ”unwindFromDetailModify”.

    Ti ringrazio anticipatamente!!!

    • Ciao Raoul,
      Una volta che colleghi il bottone all’exit event direttamente non c’è bisogno che riscrivi il performSegueWithIdentifier dentro il bottone. É probabile che sia questo il tuo errore.
      Cioè se hai collegato il bottone all’exit hai già creato un segue e la sua azione per il movimento verso quel VC. Il performSegue quindi serve solamente quando vuoi eseguire un segue che non parte direttamente da un determinato bottone o altro oggetto.

      Fammi sapere. (Scusa il ritardo ma in questo momento mi trovo a torino)

      • Raoul Gioia

        Caro Giuseppe nessun problema, anzi ti ringrazio molto, la problematica era proprio quella. Ora l’esercizio è risolto. Ti sottopongo invece un altra questione riguardante “Esercizio 0. Tabelle con più Prototype Cell” la soluzione presentata nella lezione mi da un errore sulla var cell: UITableViewCell?
        Ti posto la mia soluzione:

        if let element = list[indexPath.row] as? Contact {
        let cell = tableView.dequeueReusableCellWithIdentifier(“idCellContact”, forIndexPath: indexPath) as! ContactTableViewCell
        cell.lblContactName.text = element.name
        cell.lblContactSurname.text = element.surname
        return cell
        } else if let element = list[indexPath.row] as? Animal {
        let cell = tableView.dequeueReusableCellWithIdentifier(“idCellAnimal”, forIndexPath: indexPath) as! AnimalTableViewCell
        cell.lblAnimalName.text = element.name
        cell.lblAnimalRace.text = element.race
        return cell
        }
        return UITableViewCell()

        Dichiarando la var Cell fuori dai corpi dei rispettivi if non funziona il Downcasting. Ho Guardato le tue lezioni del corso di swift ma qualcosa mi è ancora oscuro…
        Come vedi la mia soluzione restituisce in caso di anomalia una UITableViewCell() vuota.

        • Ciao Raoul,
          Puoi dichiarare fuori dagli if la tua var cell però come oggetti UITableViewCell normale per poi castarlo come hai fatto tu nei tuoi if.

          Una cosa che potresti cambiare è l’if in guard. Per il resto mi sembra che le due celle siano quasi uguale se non per alcune cose che da qui non riesco a vedere.

          Ad esempio name, sembra che appartenga ad entrambe. Quindi forse avresti potuto creare una struttura delle classi a due livelli di profondità. Dove la prima cella contiene le informazioni comuni ad entrambe le celle e quelle sotto contengono solo gli elementi che identificato il Contact e l’Animal.
          Da valutare solamente se lo ritieni necessario o potrebbe semplificare il tuo progetto.

          Per il resto così va più che bene.

          Per il problema che hai scritto a fine commento, non ho ben capito perché il downcast non funziona. Così com’è dovrebbe andare ma dovrei vedere il resto del codice.

          Fammi sapere

          • Raoul Gioia

            Ciao Giuseppe, oggi ho provato a rimodificare il codice ma non funziona proprio ti posto il codice cosi è più chiaro:

            var cell: UITableViewCell?
            if let element = list[indexPath.row] as? Contact {
            cell = tableView.dequeueReusableCellWithIdentifier(“idCellContact”, forIndexPath: indexPath) as! ContactTableViewCell
            cell.lblContactName.text = element.name
            cell.lblContactSurname.text = element.surname
            //return cell
            }
            if let element = list[indexPath.row] as? Animal {
            cell = tableView.dequeueReusableCellWithIdentifier(“idCellAnimal”, forIndexPath: indexPath) as! AnimalTableViewCell
            cell.lblAnimalName.text = element.name
            cell.lblAnimalRace.text = element.race
            //return cell
            }
            return cell!//UITableViewCell()

            Le due classi invece sono:

            class ContactTableViewCell: UITableViewCell {

            @IBOutlet var imgContact: UIImageView!
            @IBOutlet var lblContactName: UILabel!
            @IBOutlet var lblContactSurname: UILabel!
            @IBOutlet var stkContactDetail: UIStackView!

            override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
            self.imgContact.backgroundColor = UIColor(red: 57/255, green: 150/255, blue: 197/255, alpha: 1)
            self.imgContact.layer.cornerRadius = 16
            }
            override func setSelected(selected: Bool, animated: Bool) {
            //super.setSelected(selected, animated: animated)
            // Configure the view for the selected state
            if selected == true {
            self.backgroundColor = UIColor(red: 248/255, green: 179/255, blue: 52/255, alpha: 1)
            self.stkContactDetail.hidden = false
            } else {
            self.stkContactDetail.hidden = true
            self.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
            }
            }
            }

            class AnimalTableViewCell: UITableViewCell {

            @IBOutlet var imgAnimal: UIImageView!
            @IBOutlet var lblAnimalName: UILabel!
            @IBOutlet var lblAnimalRace: UILabel!
            @IBOutlet var stkAnimalDetail: UIStackView!

            override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
            self.imgAnimal.backgroundColor = UIColor(red: 57/255, green: 150/255, blue: 197/255, alpha: 1)
            self.imgAnimal.layer.cornerRadius = 16
            }
            override func setSelected(selected: Bool, animated: Bool) {
            //super.setSelected(selected, animated: animated)
            // Configure the view for the selected state
            if selected == true {
            self.backgroundColor = UIColor(red: 248/255, green: 179/255, blue: 52/255, alpha: 1)
            self.stkAnimalDetail.hidden = false
            } else {
            self.stkAnimalDetail.hidden = true
            self.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
            }
            }
            }

            L’errore che mostra è quello nella riportato nella foto allegata:

            • Mmmh a questo punto l’unica cosa che mi viene in mente è che non hai associato la classe alla cella su storyboard. Se vuoi mandarmi il progetto in privato, gli do un’occhiata nello specifico.

              Fammi sapere

  • enricoonofri

    Ciao a tutti, dato che io ci sono cascato per mancanza di attenzione e visto che penso possa capitare anche ad altri, vorrei dire una cosa. Quando invio dei dati da tableView a VC, li modifico e li rimando indietro alla tableView tramite unwind, per riaggiornare la lista con i nuovi valori (quindi la tabella), ho bisogno di sapere esattamente l’indice del elemento cliccato in tabella che ho appena modificato. Per fare questo uso il metodo “index = self.myTable.indexPathForSelectedRow” all’interno dell’unwind, come ben scritto nel corso. In seguito con “self.myList[index.row] = newElement!” aggiorno l’array. Il mio accorgimento nasce dal fatto che inavvertitamente ho scritto “index = self.myTable.indexPathsForSelectedRows” (al plurale) e questo metodo ritorna un’array di indici. Nessun problema, ma dato che ho selezionato solo un elemento non mi serve avere una lista di indici in quanto l’indice sarà sempre e solo uno in questo caso. Perciò poi dovrei scrivere “self.myList[index[0].row] = newElement!” per aggiornare l’array. E complicherebbe inutilmente il codice. Questo è quanto!

  • Lollo82

    Ciao Peppe. Allora l’esercizio l’ho risolto. Ma non so se ho utilizzato la strada corretta. Ti spiego ciò che ho fatto…
    Ho creato la classe Appuntamento con parametro nome string ed ended bool. Nel ViewController con la TableView ho creato vari oggetti Appuntamento e ho sostituito l’array di String con un array di oggetti Appuntamento.
    Ho creato una variabile String in cui al momento della selezione di una cella vado a memorizzare la textLabel.text che corrisponde al nome selezionato.
    Per quanto riguarda la creazione delle righe ho creato una variabile row all’interno del metodo numbersOfRowInSection dopodichè scorro l’array appuntamenti e in caso la variabile .ended risulti false incrementa la row di uno.
    Mentre per la creazione delle celle all’interno del metodo cellForRowAtIndexPath ho creato un’altra variabile di array String. Successivamente scorro nuovamente l’array di appuntamenti e se la variabile .ended è false appende il parametro .nome all’array. Una volta battuti tutti gli elementi vado a printare nelle celle l’array risultante contenente solamente i nomi con ended a false.
    Seleziono il nome e vado al secondo VC, nel quale ho sostituito il tasto modifica con un tasto cancella appuntamento. Nel caso premo cancella appuntamento, nell’unwindToVC volendo cancellare solo l’elemento dalla tableView e non dall’array. Vado a pescare la variabile che avevo creato all’inizio e nella quale con il didSelectRowAtIndexPath avevo memorizzato il textLabel.text della cella e scorro tutto l’array appuntamenti paragonando questa con il parametro .nome. Appena lo incontro cambio il parametro .ended dell’oggetto a true.
    Spero di aver agito nella maniera corretta. E’ l’unico sistema che ho trovato per far si di non cancellare l’oggetto dall’array e mantenere la tabella aggiornata correttamente.
    Comunque allego tutto il codice del VC che è quello che ho modificato sostanzialmente. L’altro ho solo eliminato la textfield e modificato il nome del button.

    //

    // ViewController.swift

    // SegueConTableView

    //

    // Created by Lorenzo Cavalli on 20/09/16.

    // Copyright © 2016 Lorenzo Cavalli. All rights reserved.

    //

    import UIKit

    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var myTable: UITableView!

    var appuntamenti : [Appuntamento]!

    var currentCell : UITableViewCell!

    var selectedAppName : String?

    override func viewDidLoad() {

    super.viewDidLoad()

    let lollo = Appuntamento(nome: “Lorenzo”, ended: false)

    let valeria = Appuntamento(nome: “Valeria”, ended: false)

    let loris = Appuntamento(nome: “Loris”, ended: false)

    let franco = Appuntamento(nome: “Franco”, ended: false)

    let giorgio = Appuntamento(nome: “Pietro”, ended: false)

    appuntamenti = [lollo, valeria, loris, franco, giorgio]

    self.myTable.delegate = self

    self.myTable.dataSource = self

    // Do any additional setup after loading the view, typically from a nib.

    }

    override func didReceiveMemoryWarning() {

    super.didReceiveMemoryWarning()

    // Dispose of any resources that can be recreated.

    }

    override func viewWillAppear(animated: Bool) {

    super.viewWillAppear(animated)

    self.myTable.reloadData()

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    guard let identifier = segue.identifier else {

    return

    }

    switch identifier {

    case “segueToDetail”:

    guard let isSenderEmpty = sender else {

    return

    }

    let testo = (isSenderEmpty as! UITableViewCell).textLabel!.text!

    print(“-[segueToDetail] Sto per inviare: ” + testo)

    (segue.destinationViewController as! DetailViewController).testoRicevuto = testo

    break

    default:

    break

    }

    }

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

    var row = 0

    for x in self.appuntamenti{

    if x.ended == false{

    row += 1

    }

    }

    print(row)

    return row

    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

    {

    let cell = myTable.dequeueReusableCellWithIdentifier(“myCell”, forIndexPath: indexPath)

    var appuntamentiNonEndedName : [String] = []

    for x in appuntamenti{

    if x.ended==false{

    appuntamentiNonEndedName.append(x.nome!)

    }

    }

    cell.textLabel?.text = appuntamentiNonEndedName[indexPath.row]

    //cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

    return cell

    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    print(“Selezionata la cella (indexPath.row)”)

    currentCell = tableView.cellForRowAtIndexPath(indexPath)

    self.selectedAppName = currentCell.textLabel!.text

    print(“La variabile selectAppName è (self.selectedAppName!)”)

    let thisCell = tableView.cellForRowAtIndexPath(indexPath)

    performSegueWithIdentifier(“segueToDetail”, sender: thisCell)

    }

    @IBAction func unwind(segue: UIStoryboardSegue) {

    guard let identifier = segue.identifier else {

    return

    }

    switch identifier {

    case “unwindToVC”:

    print(“torno indietro al ViewController”)

    guard let index = self.myTable.indexPathForSelectedRow else{

    print(“Nessuna cella selezionata”)

    return

    }

    print(“(appuntamenti[index.row].nome!)” + ” ” + “(appuntamenti[index.row].ended)”)

    for x in appuntamenti{

    if x.nome == selectedAppName!{

    x.ended = true

    }

    }

    default:

    break

    }

    }

    }

  • Lollo82

    Ciao Peppe!!! Grazie mille della risposta. Non ci avevo pensato che il metodo veniva ripetuto per ogni rida della tabella.
    Ho corretto così. Ma l’ho messo nel viewWillAppear, nel viewDidAppear mi andava in crash.

    //

    // ViewController.swift

    // SegueConTableView

    //

    // Created by Lorenzo Cavalli on 20/09/16.

    // Copyright © 2016 Lorenzo Cavalli. All rights reserved.

    //

    import UIKit

    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var myTable: UITableView!

    var appuntamenti : [Appuntamento]!

    var currentCell : UITableViewCell!

    var appuntamentiNonEndedName : [String] = []

    var selectedAppName : String?

    override func viewDidLoad() {

    super.viewDidLoad()

    let lollo = Appuntamento(nome: “Lorenzo”, ended: false)

    let valeria = Appuntamento(nome: “Valeria”, ended: false)

    let loris = Appuntamento(nome: “Loris”, ended: false)

    let franco = Appuntamento(nome: “Franco”, ended: false)

    let giorgio = Appuntamento(nome: “Pietro”, ended: false)

    appuntamenti = [lollo, valeria, loris, franco, giorgio]

    self.myTable.delegate = self

    self.myTable.dataSource = self

    // Do any additional setup after loading the view, typically from a nib.

    }

    override func didReceiveMemoryWarning() {

    super.didReceiveMemoryWarning()

    // Dispose of any resources that can be recreated.

    }

    override func viewWillAppear(animated: Bool) {

    super.viewWillAppear(animated)

    self.appuntamentiNonEndedName.removeAll()

    for x in appuntamenti{

    if x.ended==false{

    appuntamentiNonEndedName.append(x.nome!)

    }

    }

    self.myTable.reloadData()

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    guard let identifier = segue.identifier else {

    return

    }

    switch identifier {

    case “segueToDetail”:

    guard let isSenderEmpty = sender else {

    return

    }

    let testo = (isSenderEmpty as! UITableViewCell).textLabel!.text!

    print(“-[segueToDetail] Sto per inviare: ” + testo)

    (segue.destinationViewController as! DetailViewController).testoRicevuto = testo

    break

    default:

    break

    }

    }

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

    var row = 0

    for x in self.appuntamenti{

    if x.ended == false{

    row += 1

    }

    }

    return row

    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

    {

    let cell = myTable.dequeueReusableCellWithIdentifier(“myCell”, forIndexPath: indexPath)

    print(“ciclo”)

    cell.textLabel?.text = appuntamentiNonEndedName[indexPath.row]

    //cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

    return cell

    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    print(“Selezionata la cella (indexPath.row)”)

    currentCell = tableView.cellForRowAtIndexPath(indexPath)

    self.selectedAppName = currentCell.textLabel!.text

    print(“La variabile selectAppName è (self.selectedAppName!)”)

    let thisCell = tableView.cellForRowAtIndexPath(indexPath)

    performSegueWithIdentifier(“segueToDetail”, sender: thisCell)

    }

    @IBAction func unwind(segue: UIStoryboardSegue) {

    guard let identifier = segue.identifier else {

    return

    }

    switch identifier {

    case “unwindToVC”:

    print(“torno indietro al ViewController”)

    guard let index = self.myTable.indexPathForSelectedRow else{

    print(“Nessuna cella selezionata”)

    return

    }

    print(“(appuntamenti[index.row].nome!)” + ” ” + “(appuntamenti[index.row].ended)”)

    for x in appuntamenti{

    if x.nome == selectedAppName!{

    x.ended = true

    }

    }

    default:

    break

    }

    }

    }

    Può andare???

    • Perfetto!!
      Sono piccoli accorgimenti che in un progetto con un enorme quantità di dati possono fare la differenza (e sopratutto possono evitare di farti perdere un mare di tempo nella scoperta del: “perché va così lento?”)

      Alla prossima e buona programmazione,
      Giuseppe Sapienza

  • Marcello

    Ciao Peppe, esercizio risolto, ma se ipoteticamente volessi inviare il numero della cella selezionato come faccio?

    • Ciao Marcello,
      Hai due metodi. O crei una variabile nella classe chiamata indexPath o qualcosa del genere. Oppure utilizzi il parametro sender: del metodo performSegue().
      Se non dovessi riuscirci, fammi sapere

      Alla prossima,
      Giuseppe Sapienza

Start typing and press Enter to search