Compatibile con Xcode 8

Esercizio Singleton. Ordinare un tavolo in pizzeria

ENTRA NEL NOSTRO GRUPPO FACEBOOK

×

Corso creare applicazioni per iOS con il linguaggio Swift

Non preoccuparti se alcuni esercizi risultano essere più complicati rispetto ad altri. Fa parte del gioco. Non si può pretendere di riuscire a risolvere degli esercizi al primo colpo. Ecco perché ogni volta che scrivo un esercizio do degli incipit su come risolverli. In questo modo cominci a formare un set di conoscenze e tool [...]

Torna a: Corso creare applicazioni per iOS con il linguaggio Swift > Applicazioni Multi Interfacce
  • Alessandro

    Ciao Beppe, sto avendo un po’ di difficoltà a svolgere questo esercizio..forse un po’ troppo complesso perché oltre a capire come applicare la lezione nuova del singleton, ha anche tanti elementi swift che vanno ricordati e rispulciati e mi distraggono dal focalizzarmi con la lezione del singleton..che ne pensi di proporre un esercizio più semplice (magari nella lezione precedente), in modo che poi ci diventa più semplice affrontare questo?

    • Ciao Ale,
      Appena posso modifico la lezione e aggiungo qualche esercizio più semplice. Nel frattempo se hai dei dubbi sul seguente esercizio, apri un topic oppure scrivi qui cosa hai trovato difficile. Così vediamo di risolverlo passo passo!

      • alearcy

        Sono riuscito a farlo tutto aggiungendo anche la possibilità di inserire i tavoli e cambiarne lo stato in base a se è prenotato o no. Però ho fatto tutto senza il singleton, perché non riesco a capire la necessità di rendere singleton sia l’utente che la prenotazione..nella realtà io ho app multiutente e dei DB che mi dicono se l’utente ha già un tavolo oppure no, basta leggere dal DB..è qui che non capisco appieno l’utilità del singleton..

        • É molto semplice. Spesso e volentieri un utente, nella fretta, esce e rientra più volte nelle stesse pagine dell’applicazione o semplicemente crea e non completa un’azione.

          Quindi se non vengono gestite opportunamente, queste istanze rischiano di rimanere in memoria (con il conseguente problema dello stackoverflow se non eliminate) oppure di intasare un server se le connessioni non vengono interrotte o le istanze eliminate opportunamente.

          É lo stesso problema che accade ai siti di prenotazione dei voli dove l’istanza, cioè la sessione di prenotazione di un volo è singleton, ovvero non puoi prenotare due voli contemporaneamente su due sessioni separate (sue due pagine ad esempio). Loro lo bloccano coi cookie o con la shared istance di un oggetto prenotazione.

          Un pattern è solo un modo di risolvere un problema. Non aggiunge specifiche in più e non è obbligatorio utilizzarlo. É solo uno dei tanti modi per arrivare ad una soluzione.
          Tu nel tuo esempio hai gestito la cosa con una variabile che è l’equivalente di un singleton non “patterizzato”. Cioè avrai un oggetto prenotazione e un oggetto utente con flag. Il tuo flag ti crea la singolarità.

          Lo stesso problema poteva essere risolto dal lato software con l’implementazione di un singleton che SICURAMENTE non avrebbe creato istanze multiple sul server e di conseguenza non avresti avuto bisogno di un check sul flag.
          Cioè un utente, su DB, ha una casella dove viene conservato il riferimento alla prenotazione. L’app controlla che la casella è piena e recupera l’istanza tramite una query, se è vuota la riempie con l’istanza presente in app.
          Quindi una singola query diretta sulla proprietà prenotazione dell’utente.

          Nel tuo caso, fai una query sul flag e poi sull’istanza?

          Ad ogni mondo il Singleton, in app, ti permette di recuperare la stessa istanza da pagine diverse dell’applicazione. Senza saresti obbligato a passare il riferimento dell’oggetto in più VC. Idem per l’oggetto prenotazione.

          Cioè anche con DB, fai una sola query che ti conserva il riferimento alla prenotazione e all’utente. Se no il rischio è che, ogni volta che ti serve l’oggetto utente, fai una query al DB.
          Non so se mi sono spiegato. Il problema principale verte su questi due ultimi concetti.

  • Francesco

    Ciao Peppe,

    scusa la domanda forse banale ma non riesco a collegare la cosa.

    Nel Tuo esempio nella classe utente hai fatto la singleton in modo nella classa prenotazione in un altro, mi spiego:

    nella classe utente hai fatto

    static let sharedIstance: Utente = Utente()

    nella classe prenotazione

    static var sharedIstance = Prenotazione()

    come mai nella classe prenotazione non hai fatto come la classe utente?
    Grazie

    • Ciao Francesco,

      Il modo di scrivere le due variabili è equivalente, nel primo ho specificato anche il tipo :Utente, mentre nel secondo l’ho omesso.

      per l’errore della label prova a fare un update frame dal resolve auto layout issues. Oppure controlla che non ci siano vincoli in più per la label (vedi dal document outliner selezionandoli uno per uno oppure dal pannello Size Ispector)

      Aspetto tue notizie!

      • Francesco

        Grazie Peppe
        Problema risolto

        • Non c’è di che Francesco,

          Per qualsiasi cosa, anche quella che può sembrare banale, chiedi pure!

  • Leonardo Bacciottini

    Posto la mia soluzione alla struttura delle classi, se avete qualche accorgimento da darmi ditemelo pure :)

    class Utente {

    static var singleton = Utente()

    var nome: String?

    var numerotelefono: String?

    private init() {}

    }

    class Prenotazione {

    var utente: Utente?

    var numeroutenti: Int?

    var codice: String?

    static var singleton = Prenotazione()

    private init() {}
    }

    class Pizzeria {

    var tavolidisponibili = [2: “AA”, 4: “BB”, 6: “CC”, 3: “DD”, 10: “EE”]

    func status (prenotazione prenotazione: Prenotazione)->Bool {

    for numero in self.tavolidisponibili.keys{

    if numero == prenotazione.numeroutenti {

    prenotazione.codice = self.tavolidisponibili[numero]

    return true
    }

    }

    return false
    }

    static let singleton = Pizzeria()

    private init() {}
    }

  • nickbonny

    Ciao Peppe, mi dispiace ma io non riesco proprio a capire che utilità abbia in questo esercizio usare i singleton sia all’interno della classe utente che nella class prenotazione..cioè usando delle class normali cosa sarebbe cambiato?

    • Assolutamente niente Nick. Un pattern è un modo di programmare le cose non è una soluzione differente. É semplicemente prendere ciò che si ha appreso ed utilizzarlo con una tecnica differente.

      In una classe normale avresti avuto una proprietà, ad esempio “Prenotato: Bool” che ti avrebbe indicato se la prenotazione era stata effettuata oppure no. In questo modo salti una creazione di una proprietà e di controlli inutili perché sai che esisterà solo e solamente un oggetto.

  • nickbonny

    Ciao, sono sempre io ahah! Nel tuo progetto, nel OrderViewController, hai questa stringa:
    if pizzeria.checkTavolo(&Utente.sharedIstance.prenotazione) a cosa serva il simbolo &?

    • Ciao Nick!!
      Per me è un piacere rispondere, anzi più commenti ci sono è meglio è :P

      Per la tua domanda, il simbolo & viene utilizzato per le funzioni che hanno parametro di tipo inout. Puoi studiare questa tipologia di funzioni nel corso gratuito.

      Fammi sapere!

  • Gabriele Brescancin

    Ciao a tutti! Nel File pizzeria.swift c’è un unico metodo. il parametro in ingresso è perPrenotazione di tipo Prenotazione. Come in altri casi già visti durante il corso, succede che una variabile (oggetto) che viene passata in ingresso ad una func non viene dichiarata prima. In pratica l’oggetto viene instanziato solamente quando viene chiamata la func. Prima non esiste. È corretto? Domanda un po’ banale e credo di essermi già risposto, voglio solo avere la conferma. Grazie.

    • Ciao Gabriele,
      Esattamente è un sistema che viene utilizzato per evitare di creare degli oggetti quando non servono. Nel nostro caso l’abbiamo utilizzato per creare la prenotazione solo quando effettivamente serviva all’utente (cioè quando preme il bottone)

  • Lollo82

    Ciao Peppe. Allora più o meno ho capito.
    L’unica cosa che non riesco a capire dal tuo codice è perchè hai assegnato Utente.sharedInstance alla costante mioUtente.
    Ho provato a non utilizzarla e assegnare i valori delle textfield utilizzando i percorsi:

    Utente.sharedInstance.prenotazione.numeroClienti = Int(self.persone_field.text!)

    Utente.sharedInstance.nome = self.nome_field.text!

    Utente.sharedInstance.telefono = Int(self.telefono_field.text!)

    e funziona uguale. Mi son perso qualcosa??? Infatti nel viewController assegnato alla cancellazione dell’ordine per passare a nil i vari parametri utilizzi il percorso Utente.sharedInstance.
    Grazie mille delle delucidazioni!!!

    • Ciao Lollo,
      Non ti sei perso assolutamente niente. Il fatto che io abbia passato Utente.sharedIstance alla costante non e poi abbia utilizzato questa per eseguire le operazioni non comporta nessuna modifica.
      Infatti quando si passa un oggetto (di qualsiasi tipo, singleton o no) ad una variabile o costante, si passa il riferimento. Cioè la variabile/costante in realtà punta all’oggetto originale. Nel nostro caso l’Utente.

      Spero di essere stato chiaro,
      Giuseppe

    • Marco Dognini

      Grazie Lollo, avevo il tuo stesso dubbio e mi hai risparmiato la stesura del commento!

  • Marco Dognini

    Ciao Peppe,
    cercando di aggiungere le prenotazioni multiple ho notato una cosa che non mi è chiara del Singleton.
    Prendo il tuo esercizio come esempio.
    Se volessi stampare, oltre al codice del tavolo, anche il nome ed il numero di telefono nell’order View controller non sarei in grado di farlo, perché stamperebbe sempre nil.

    Utente.sharedistance.nome = name_text.text
    print(Utente.sharedistance.nome) //stampa nil

    Sarei quindi costretto a passare la costante mioUtente, quindi che senso ha il Singleton?

    la gestione multipla delle prenotazioni pensavo di risolverla facendo un append all’array di prenotazioni della mia istanza singleton di Utente, ma non funziona, mi rimane sempre vuoto.

    • Ciao Marco,
      scusa il ritardo. Ci sarà sicuramente qualche problema perché il Singleton serve proprio a questo ad avere un oggetto condiviso in tutte le classi.
      Poi è normale che, se per esempio, si passa nil alla Utente.sharedIstance quell’oggetto si distrugge.

      In caso fammi vedere il codice,
      P.S. Se non lo hai ancora fatto siamo su slack http://www.xcoding.it/slack/

Start typing and press Enter to search