Core Data e relationship tra Entity

Nella precedente lezione ti ho lasciato con le funzioni principali del Core Data: inserimento, cancellazione e ricerca dei vari NSManagedObject all'interno del tuo NSManagedObjectContext (cioè lo spazio dove i dati persistenti risiedono). Tutte le operazioni viste fin ora, però, riguardano esclusivamente una tipologia d'oggetto che nasce e muore da solo. Cioè un oggetto che non ha [...]

Torna a: Corso creare applicazioni per iOS con il linguaggio Swift > Salvare dati in Memoria
  • nickbonny

    Ciao Peppe, non mi è chiara una cosa..

    Quando per esempio nella funzione addNuovaMateria vado a fare:
    let nuovaMateria = Materia(entity: entityMateria! ecc…), perché mi suggerisce la parte tra parentesi di associare un entity e un context??
    Cioè io non ho specificato nessun init nella Class Materia..

    Grazie in anticipo

    • Ciao Nick,
      Anche in questo caso la risposta è più semplice di quello che si può pensare. La classe NSManagedObject Materia è, per l’appunto, una subclass della NSManagedObject, nella lezione precedente avevo scritto che non era necessario aggiungere il metodo init perché già presente nella super classe.
      In questo caso infatti non l’ho riscritto ma l’ho comunque utilizzato perché presente nella classe genitore.

  • fabiod

    Ciao Giuseppe, grazie alle tue lezioni favolose!!, sono riuscito nell’impresa di mettere in pratica i concetti chiave della lezione. Ed ho aggiunto pure qualche altra Entity. Tuttavia dato che ho momentaneamente saltato le lezioni sulle tableview (alle quali sto per tornare) ho utilizzato solo bottoni e label e textfield. Inoltre, come ho fatto per altri esercizi, prima ne ho realizzato una versione con un singolo ViewController per provare la parte essenziale del codice, poi sto per complicarmi la vita con varie opzioni da sviluppare in una struttura più articolata di ViewController. Insomma sono arrivato in quest’ultima fase.
    Ed ho una serie INFINITA di domande da farti.
    Ho aggiunto gli altri ViewController in questo modo:
    VC1 dove effettuare il login;
    VC2 dove eventualmente registrarsi.
    VC3, VC4 e VC5 dove settare alcune impostazioni;
    VC6 quello principale (dove aggiungo i voti alle materie);
    VC7-VC8 collegati solo al precedente dove visualizzo la situazione generale delle materie.
    Ecco le domande.
    Il VC2 per la registrazione deve tornare al VC1 o può proseguire oltre? Da semplice utente preferirei proseguire oltre senza dover ritornare alla pagina iniziale per scrivere nuovamente nome e password per accedere. Tu che ne pensi? Inoltre dopo la registrazione (dato che è la prima volta che uso l’app), si passa a VC3-VC4-VC5 (messi in fila) in cui settare le impostazioni usando l’NSUserDefault per salvare i dati (il nome e il numero delle materie, il colore dello sfondo e altre cose inutili come nome scuola, classe, anno scolastico ecc.). Dopo di ciò si passa al VC6 quello principale (dove aggiungo i voti). Il problema è che vorrei realizzare le seguenti possibilità: 1) al VC6 posso arrivarci anche direttamente dal login VC1 se non devo registrarmi (QUESTA COSA NON LA SO FARE!!); 2) nel VC6 ho i pulsanti per tornare a VC1 (login) ma anche quello che torna alle impostazioni (VC3-VC4-VC5) per eventualmente modificarle (inoltre il VC6 si collega ai dettagli materie cioè VC7 e VC8).
    Insomma mi sono confuso con la struttura dei ViewController e dei relativi Segue.
    Inizialmente li avevo messi semplicemente tutti i fila. Mi era riuscito tutto ma non riuscivo a saltare dal VC1 al VC6.
    Che devo fare??? Come li strutturo tutti questi ViewController? Ci vogliono più NavigationController?
    Grazie mille in anticipo,
    ciao, Fabio

    PS: avevo dimenticato la seconda questione.
    Se voglio cambiare il colore ad un pulsante scrivo dentro la @IBAction che lo gestisce: sender.backgroundColor = UIColor(red: 0.856136, green: 0.460216, blue: 0.671408, alpha: 1)
    Ma se voglio fare la stessa operazione dentro “func viewDidLoad()” per settare il colore quando si carica la schermata, non so più come identificare i vari bottoni (dato che non ho più il riferimento al sender). Dove lo trovo questo riferimento identificativo per ogni bottone?
    Se dentro la “IBAction func” del bottone metto “print(sender)” in fase di esecuzione stampa tutta una serie di dati del bottone. Uno di quelli si può usare per identificarlo? e Come?
    Oppure devo creare una IBOutlet per ogni bottone dello schermo per averne un riferimento? O c’un altro modo?
    E per modificare lo sfondo della View?

    • Ciao Fabio,
      Partiamo dalle utile domande.
      — Per cambiare il colore dei bottoni, crea delle IBOultet e poi con quelle modifichi il colore dal viewDidLoad. Anche se sembra una scelta banale è proprio così che si fa (non spaventarti di utilizzare implementazioni semplici, per l’80% delle volte i problemi si risolvono con soluzioni semplici).
      — Per modificare lo sfondo della view principale, devi accedere alla proprietà view del ViewController. Quindi ti basta scrivere, self.view.backgroundColor o quello che ti serve a te.

      — Per poter saltare da un VC ad un altro senza dover passare dagli intermedi, puoi utilizzare gli Identifier dei ViewController più o meno come ho fatto vedere nella lezione della creazione degli slider.
      Per esempio, puoi scrivere così:

      let storyboard = UIStoryboard(name: “Main”, bundle: nil)
      let vc = storyboard.instantiateViewControllerWithIdentifier(“IDENTIFIER DEL TUO VC”) as! ClasseTuoVCViewController
      self.navigationController?.pushViewController(vc, animated: true)

      Grazie a questo codice potrai spostarti avanti ed indietro saltando i VC nel mezzo. Assicurati eprò di utilizzare il Navigation Controller.

      • Se dovessero esserci altri problemi, questioni o domande, scrivi pure

        • fabiod

          Giuseppe grazie mille per la tempestività della risposta. La parte degli IBOutlet l’ho capita; quella sugli slider riguarda una tua lezione che avevo momentaneamente saltato e che vado immediatamente a studiare. Ti farò sapere.

        • fabiod

          OK, provato e funziona tutto. Naturalmente se faccio un salto in avanti tra ViewController con questo sistema, l’array del Navigation Controller non viene aggiornato. Quindi se dal VC appena raggiunto voglio fare dei passi indietro non posso più farlo con unwind segue ma devo sempre usare il pushViewController. Giusto? O c’è un modo per aggiornare l’array del NavigationController in corrispondenza al VC corrente?
          Comunque così funziona. Grazie mille nuovamente!!
          PS: Dovevo scriverti ieri mattina, al posto di perdere un fine settimana intero a fare prove inutili..!

          • Puoi utilizzare l’unwind senza nessun problema. L’aggiornamento dell’array è una procedura complicata e che sconsiglio vivamente.

            O comunque se vuoi tornare indietro puoi semplicemente utilizzare un dismiss del viewcontroller corrente.

            Considera che il metodo che ti ho detto viene utilizzato, per esempio, quando si vuole accedere ad un VC condiviso da tutti. Tipo la pagina Contattami, Home o cose di questo tipo.
            L’applicazione di Facebook utilizza questo sistema per portarti ad un post quando lo selezioni dalla pagina delle notifiche.

            Per il resto non c’è di che. Ne approfitto per dirti che puoi trovarci su Telegram nel seguente gruppo ufficiale di xcoding https://telegram.me/xcoding_dev

            • fabiod

              Ok grazie. Mi sa che avevo sbagliato qualcosa. In pratica se saltavo da VC1 a VC5 con il pushViewController, poi non funzionava il ritorno dal VC5 al VC2 con unwind; se invece (sempre nella stessa esecuzione) ritornavo ad home, poi scorrevo in avanti tutti i VC dal VC1 al VC5, in questo caso l’unwind dal VC5 al VC2 funzionava. Boh.
              Volevo chiederti anche un’altra cosa (lo so, ti sto tormentando…mi butterai fuori dal corso!!!..)
              Vorrei aggiungere anche la classe Utente (o Alunno). Quindi avevo pensato di creare un’altra Entity, (chiamata Utenti), con le proprietà “nome”, “cognome”, e “Materia” (di tipo NSSet). Poi creare una array nell’NSUserDefault con la lista degli utenti creati. Poi da codice nell’extension della classe Utenti che si verrà a creare, dovrei inserire i due metodi per aggiungere o togliere una materia da un Utente. Infine nella classe CoreDataController inserire i metodi per aggiungere un nuovo utente.
              Tu che ne pensi?

  • fabiod

    Ciao Giuseppe, eccomi con un po’ di domande del fine settimana.
    In realtà una sola, fondamentale.
    Se in un progetto finito e funzionante voglio aggiungere un attributo ad un Entity (o peggio ancora un Entity nuovo di zecca da mettere in relazione con uno dei già presenti), che devo fare?
    Perché io ho provato ad aggiungere anche solo un attributo a Materia nel xcdatamodeld, poi ho aggiunto nell’extension Materia il corrispondente “@NSManaged var”, ma il risultato è stato disastroso. Un fatal error che non finisce mai.
    È una cosa che si può risolvere?
    Grazie, ciao
    Fabio

    • Fabio, ho risposto a tutte nella lezione successiva ;)

      • fabiod

        ok grazie, l’ho gia “divorata..”

  • nickbonny

    Ciao Beppe,
    io avrei bisogno di integrare il core data con il cloudkit. Cioè mi sto chiedendo se il modo corretto sia implementare il core data con tutte le sue entity e le relazioni nell’applicazione e poi mandare ad iCloud le informazioni perché vengano salvate sul database, o esiste un modo migliore?
    In tal caso come devo fare? XD

  • Lollo82

    Ciao Peppe. Come al solito sei stato molto chiaro. Una cosa volevo chiederti.
    Allora qua si dà per scontato che ipotesi io scarico la app dall’appStore e mi trovo a partire con 0 materie. Quindi io inserisco la mia bella matematica col suo voto, storia, geografia eccetera.
    Ma se io volessi che al momento dell’installazione sul dispositivo all’interno del coreData vi fossero già presenti le materie piuttosto che chessò i ripiani del frigo, della dispensa o altre cose (e queste non fossero più modificabili). Posso inserirli manualmente al momento della creazione dell’xcatdatamodel??? Oppure devo comunque creare la funzione aggiungiMaterie e poi tramite NSUserDefault aggiungere queste tramite la funzione nel caso in cui fosse il primo avvio dell’app??? Non so se ho spiegato bene ciò che vorrei ottenere. Grazie mille come sempre Peppe.

    • Ciao Lollo,
      Nel caso volessi utilizzare il Core Data con dei dati di default già presenti all’avvio, potresti mettere una variabile booleana (salvata nell’NSUserDefaults) che se è true attiva delle funzioni che popolano il Core Data con dei dati ti partenza.
      Una volta finito di popolare il core, passi la var booleana a false in modo da evitare che vengano eseguite queste operazioni ai successivi avvii.

      Quindi si, l’intuizione che hai avuto era corretta ;)

      Alla prossima!
      Giuseppe Sapienza | xCoding.it

      • Lollo82

        Ok capisco. Speravo ci fosse un metodo più rapido per aggiungere oggetti in manuale. :)
        Grazie infinite di tutto.

        • Che mi risulta mi sa di no! L’altro sistema potrebbe essere quello di salvare i dati su un server online e scaricarli da lì (in modo da evitare di dover aggiornare l’app solo per sistemare i dati di default dell’applicazione).

Start typing and press Enter to search