Dove posizionare il “Core Data Stack” in un’applicazione Cocoa / Cocoa Touch

Nel modello di dati di base dell’iPhone, Apple inserisce lo stack di dati principali nel delegato dell’app.

La mia inclinazione iniziale è comunque quella di spostare questo codice nella propria class, la cui responsabilità è di gestire la gestione del Core Data Stack.

In genere racchiudi questa funzionalità all’interno della sua class o la lasci nel Delegato app?

Riepilogo: non è necessario creare un singleton per gestire lo stack dei Core Data; in effetti, è probabile che ciò sia controproducente.

Lo stack di Core Data viene creato dal delegato dell’applicazione. È importante sottolineare, tuttavia, come mostrano tutti gli esempi, lo stack (principalmente il contesto dell’object gestito) non viene recuperato direttamente dallo stack (*). Invece il contesto viene passato al primo controller di visualizzazione e da questi in un contesto o un object gestito viene passato da un controller di vista al successivo (come descritto in Accesso allo stack di dati principali ). Questo segue lo schema di base per iPhone tutte le applicazioni: si passano dati o un controller modello da un controller vista al successivo.

Il ruolo tipico del singleton come descritto qui è come un controller del modello. Con Core Data, il contesto dell’object gestito è già un controllore del modello. Ti dà anche la possibilità di accedere ad altre parti dello stack, se necessario. Inoltre, in alcune situazioni (come descritto nella documentazione) potresti voler utilizzare un contesto diverso per eseguire un insieme discreto di azioni. Di conseguenza, l’unità di misura appropriata per un controller di visualizzazione è di solito un contesto di object gestito, altrimenti un object gestito. L’uso e il passaggio di un object singleton che gestisce uno stack (e dal quale si recupera un contesto) tipicamente nel migliore dei casi introduce un livello inutile di riferimento indiretto e, nel peggiore dei casi, introduce rigidità applicativa non necessaria.

(*) Nessun esempio recupera il contesto utilizzando:

[[UIApplication delegate] managedObjectContext]; 

Ho una class singleton che ho lasciato fare la mia gestione dei dati di base e non la lascio sul delegato dell’app. Preferisco non ingombrare la class del delegato dell’app con metodi che potrei aver bisogno per il conviny come il recupero di determinati oggetti, ecc

Lascio la logica dei dati di base nel delegato App per i seguenti motivi:

1) Non vedo alcun vantaggio reale nello spostare questo codice in altre classi: il concetto di delega è perfettamente soddisfatto dalla logica dei dati di base gestita dal delegato App poiché il modello di dati di base è in realtà una parte fondamentale della vostra applicazione;

2) In tutto il codice di esempio che ho visto, inclusi gli esempi di Apple, i dati di base sono gestiti dal delegato di App;

3) Anche nei libri di Core Data è prassi comune che il delegato di App gestisca il codice relativo ai dati di base;

4) Personalmente non penso che la leggibilità o qualsiasi altra cosa sia effettivamente migliorata avendo classi ad hoc per i dati principali, ma questa è una questione di gusto personale e non discuterò qui quale approccio sia il migliore. Per me, la semplicità pur mantenendo la funzionalità è importante.

La domanda che mi pongo, nel tuo caso, è “a chi appartiene lo stack di Core Data”? Lo stesso dato è in realtà provincia dell’applicazione, vero? (CF Core Data su Mac, dove potresti avere un’applicazione in grado di lavorare con più documenti alla volta, quindi lo stack di Core Data appartiene a ciascun documento.)

In qualsiasi applicazione Cocoa / Cocoa Touch, il Delegato app è di solito il mezzo preferito per personalizzare il comportamento dell’applicazione, quindi questo è il posto naturale per lo stack Core Data.

Ora, il problema che sospetto che tu stia avendo è che è sbagliato scrivere costantemente cose come:

 NSManagedObjectContext *context = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

Quello che faccio di solito in questi casi sono le funzioni di scrittura (non i metodi) come questo:

 NSManagedObjectContext *UIAppManagedObjectContext() { return [*(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; } 

Scrivo una funzione simile per NSPersistentStoreCoordinator e NSManagedObjectModel . Ho inserito tutti questi file nel file .h / .m del Delegato dell’app, poiché anche questi sono oggetti a livello di applicazione.

Lo elenco solo in una nuova risposta. (Ho scartato la mia precedente class FJSCoreDataStack in favore di questo)

Il mio nuovo modo di gestirlo è stato quello di usare una categoria su NSManagedObjectContext. Ive ha aggiunto i seguenti metodi di class:

 + (NSManagedObjectContext *)defaultManagedObjectContext; + (NSManagedObjectContext *)scratchpadManagedObjectContext; + (NSManagedObjectModel *)managedObjectModel; + (NSPersistentStoreCoordinator *)persistentStoreCoordinator; + (NSString *)applicationDocumentsDirectory; 

Ciò mantiene tutto fuori dal mio delegato app e dà accesso singleton se dovessi scegliere di usarlo. Tuttavia, utilizzo ancora l’injection dependence dal Delegato app (come ha detto mmalc, introduce l’inflessibilità nel mio codice). Ho semplicemente spostato tutto il codice “Core Data Stack” nella categoria NSManagedObjectCOntext.

Mi piace passare il riferimento in giro, soprattutto perché ho un buon metodo “scratchpad context”. Ciò mantiene flessibili i miei controller di visualizzazione poiché non li ho mai impegnati in “defaultManagedObjectContext”.

Rilevante anche per la conversazione nel mondo di iPhone (e potrebbe influire sulla tua architettura): NSFetchedResultsController e costruzione di NSFetchRequests

Sono favorevole all’idea che il delegato dell’app conosca il punto di partenza del modello e che il modello sappia dove si trova il contesto dell’object gestito. Il Core Data- “ness” del modello sembra un dettaglio di implementazione del modello per me, le classi controller (come il delegato dell’app) dovrebbero solo chiedere “dammi queste informazioni sul modello” e il modello dovrebbe sapere come rispondere quella domanda. Quindi avere un object di dati di base disponibile attraverso un object controller sembra un’astrazione che perde.