Core data fra Scratch: NSFetchedResultsController
27
Del
5
Del
Dette Cyber mandag Envato Tuts + Kursene vil bli redusert til bare $ 3. Ikke gå glipp av
Dette innlegget er en del av en serie kalt kjernedata fra Scratch.Core data fra Scratch:. Relasjoner og Mer FetchingCore data fra Scratch: Mer NSFetchedResultsController
I forrige avdrag av denne serien, vi dekket de grunnleggende av kjernedata rammeverket. Det er på tide vi setter vår kunnskap til å bruke ved å bygge et enkelt program drevet av kjernedata.
I denne opplæringen, vil vi også møte en annen stjerne spiller av Core data rammer, NSFetchedResultsController klasse. Søknaden at vi er i ferd med å skape forvalter en liste over gjøremål. Med søknaden, kan vi legge til, oppdatere og slette gjøremål. Du vil raskt lære at NSFetchedResultsController klassen gjør dette veldig enkelt å gjøre.
1. Prosjektet Setup
Åpne Xcode, velger du Nytt > Prosjekt ...
fra Fil
menyen, og velg Enkel visning Application
mal fra iOS >
Søknad
kategori.
Navn prosjektet Ferdig
, sette Enheter
til iPhone
, og fortelle Xcode hvor Vil du lagre prosjektet.
Fordi vi valgte Enkel visning Application
mal, har Xcode ikke skapt en Core Data oppsett for oss. Men å sette opp grunndata stabelen skal være enkelt, hvis du har lest de tidligere avdrag av denne serien.
2. Kjernen data Setup
Åpne gjennomføringen fil av programmet delegat klassen, TSPAppDelegate.m
, og erklærer tre eiendommer i en privat klasse forlengelse, managedObjectContext, managedObjectModel, og persistentStoreCoordinator. Hvis du er forvirret av dette trinnet, så anbefaler jeg at du besøker den første artikkelen i denne serien, som dekker kjernedata stable i detalj.
Legg merke til at jeg har også lagt til en import regnskapet for kjernedata rammen på toppen av TSPAppDelegate.m
#import "TSPAppDelegate.h" #import. < CoreData /CoreData.h >interface TSPAppDelegate ()property (sterk, nonatomic) NSManagedObjectContext * managedObjectContext;property (sterk, nonatomic) NSManagedObjectModel * managedObjectModel;property (sterk, nonatomic) NSPersistentStoreCoordinator * persistentStoreCoordinator;end
Som du kanskje husker, er kjernen data stabelen satt opp dovent. Dette betyr at vi instantiate klarte objektet kontekst, klarte objektmodellen, og den vedvarende butikken koordinator øyeblikket de trengs av programmet. Med andre ord, er de nevnte objektene instansiert i getter til sine tilsvarende egenskaper. Følgende kodesnutter bør se veldig kjent Anmeldelser - (NSManagedObjectContext *) managedObjectContext {if (_managedObjectContext) {return _managedObjectContext.; } NSPersistentStoreCoordinator * koordinator = [selvtillit persistentStoreCoordinator]; if (koordinator) {_managedObjectContext = [[NSManagedObjectContext Alloc] init]; [_managedObjectContext setPersistentStoreCoordinator: koordinator]; } Returnere _managedObjectContext;} - (NSManagedObjectModel *) managedObjectModel {if (_managedObjectModel) {return _managedObjectModel; } NSURL * modelURL = [[NSBundle mainBundle] URLForResource: @ "Ferdig" withExtension: @ "momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL]; returnere _managedObjectModel;} - (NSPersistentStoreCoordinator *) persistentStoreCoordinator {if (_persistentStoreCoordinator) {return _persistentStoreCoordinator; } NSURL * applicationDocumentsDirectory = [[[NSFileManagers defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject]; NSURL * storeURL = [applicationDocumentsDirectory URLByAppendingPathComponent: @ "Done.sqlite"]; NSError * error = null; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [selvtillit managedObjectModel]]; if ([_ persistentStoreCoordinator addPersistentStoreWithType: NSSQLiteStoreType konfigurasjon: nil URL: storeURL alternativer: null feil: & error]) {NSLog (@ "Uløste feil% @,% @", feil, [error Userinfo]); abortere (); } Returnere _persistentStoreCoordinator;}
Det er tre ting du bør være klar over. Først datamodellen, som vi vil lage neste, får navnet Done.momd
. For det andre vil vi nevne støtte butikken Ferdig
og det vil være en SQLite
database. Tredje, hvis kompet butikken er uforenlig med datamodellen, påberope vi avbryte, drepte søknaden. Som jeg nevnte tidligere i denne serien, mens dette er greit under utvikling, bør du aldri kalle abort i produksjonen. Vi vil se vandringer og inkompatibilitet problemer senere i denne serien.
Mens vår søknad ikke vil krasje hvis du prøver å kjøre den, Core data bunken ikke vil bli riktig satt opp. Grunnen er enkel, vi har ikke skapt en datamodell ennå. La oss ta vare på det i neste trinn.
3. Opprette datamodellen
Velg Nytt > Fil ...
fra Fil
menyen og velg Data Model
fra iOS > Kjernen data
kategori.
Gi filen navnet Ferdig
, dobbeltsjekke at det er lagt til Ferdig
målet, og fortelle Xcode der den trenger å bli frelst .
Datamodellen kommer til å være svært enkel. Opprett en ny enhet og gi den navnet TSPItem
. Legg tre attributter til foretaket,
navn av typen String
, createdAt av type Dato
, og gjort av type boolsk
.
Merk attributtene som kreves, ikke valgfritt, og sette standardverdien av ferdig attributt til NO.
The Core data stabelen er satt opp og datamodellen er riktig konfigurert. Det er på tide å bli kjent med en ny klasse av Core data rammer, NSFetchedResultsController klasse.
4. Administrerende data
Denne artikkelen handler ikke bare om den NSFetchedResultsController klassen, det handler om hva NSFetchedResultsController klassen gjør bak kulissene. La meg forklare hva jeg mener med dette.
Hvis vi skulle bygge søknaden vår uten NSFetchedResultsController klasse, ville vi trenger å finne en måte å holde programmets brukergrensesnitt synkronisert med dataene som forvaltes av grunndata. Heldigvis har kjernedata en elegant løsning på dette problemet.
Når en rekord er innsatt
, oppdatert
, eller slettet
i en styrt objekt kontekst, de administrerte objektkontekst poster en melding via varslingssenteret. En administrert objekt sammenheng kan legge inn tre typer varslinger:
NSManagedObjectContextObjectsDidChangeNotification. Denne meldingen er lagt ut hver gang en rekord i administrerte objektet sammenheng er satt inn, oppdatert eller slettet
NSManagedObjectContextWillSaveNotification : Denne meldingen er postet av den administrerte objektet sammenheng før
ventende endringer er forpliktet til å støtte butikken
NSManagedObjectContextDidSaveNotification. Denne meldingen er postet av den administrerte objektet sammenheng umiddelbart etter
ventende endringer har vært opptatt av å støtte butikken.
Innholdet i disse meldingene er identiske, altså objektet eiendom varselet er NSManagedObjectContext eksempel at postet meldingen og meldingen er userinfo ordboken inneholder postene som ble innsatte
, oppdatert
, og slettet
.
Kjernen er at det krever en god del av standardkoden for å holde resultatene av en hente be oppdatert. Med andre ord, hvis vi skulle lage søknaden vår uten å bruke NSFetchedResultsController klasse, ville vi måtte iverksette en mekanisme som overvåket klarte objektet kontekst for endringer og oppdatere brukergrensesnitt tilsvarende. La oss se hvordan NSFetchedResultsController kan hjelpe oss med denne oppgaven.
5. Sette opp brukergrensesnittet
Arbeide med NSFetchedResultsController klassen er ganske enkelt. En forekomst av NSFetchedResultsController klassen tar hente forespørsel og har en delegat objekt. Den NSFetchedResultsController objekt sørger for at det holder resultatene av hente be deg oppdatert ved å overvåke klarte objektet sammenheng hente forespørselen ble henrettet av.
Hvis NSFetchedResultsController objektet er varslet om eventuelle endringer ved NSManagedObjectContext gjenstand for hente forespørsel, varsler den sin delegat. Du lurer kanskje på hvordan dette er forskjellig fra en visning controller direkte overvåking av NSManagedObjectContext objektet. Det fine med NSFetchedResultsController klassen er at den behandler meldingene den mottar fra NSManagedObjectContext objektet og forteller representanten bare det den trenger å vite for å oppdatere brukergrensesnitt som respons på disse endringene. Metodene for den NSFetchedResultsControllerDelegate protokollen bør avklare dette Anmeldelser - (void) controllerWillChangeContent: (NSFetchedResultsController *) kontrolleren; - (void) controllerDidChangeContent:. (NSFetchedResultsController *) kontrolleren; - (void) controller: (NSFetchedResultsController *) controller didChangeSection: (id < NSFetchedResultsSectionInfo >) sectionInfo atIndex: (NSUInteger) sectionIndex forChangeType: (NSFetchedResultsChangeType) type; - (void) controller: (NSFetchedResultsController *) controller didChangeObject: (id) anObject atIndexPath: (NSIndexPath *) indexPath forChangeType: (NSFetchedResultsChangeType) type newIndexPath: (NSIndexPath *) newIndexPath;
De underskrifter av de ovennevnte delegere metoder avsløre den egentlige hensikten med NSFetchedResultsController klassen. På iOS, ble NSFetchedResultsController klasse designet for å håndtere dataene som vises av en UITableView eller en UICollectionView. Det forteller sin delegat nøyaktig hvilke poster endret, hvordan du oppdaterer brukergrensesnittet, og når man skal gjøre dette.
Ikke bekymre deg hvis du fremdeles er usikker om hensikten eller fordeler av NSFetchedResultsController klassen. Det vil være mer fornuftig når vi har implementert NSFetchedResultsControllerDelegate protokollen. La oss se vår søknad og sette NSFetchedResultsController klassen å bruke
Trinn 1:. Fyller storyboardet
Åpne prosjektets hovedstoryboard, Main.storyboard
, velg View Controller Scene
, og legge det i en navigeringskontrolleren ved å velge Embed In > Navigation Controller
fra Editor
menyen.
Dra en UITableView objekt i View Controller Scene
, skape et utløp i TSPViewController klasse, og koble den i dreieboken. Ikke glem å gjøre TSPViewController klasse i samsvar med UITableViewDataSource og UITableViewDelegate protokoller
#import < UIKit /UIKit.h >interface TSPViewController. UIViewController < UITableViewDataSource, UITableViewDelegate >property (svak, nonatomic) IBOutlet UITableView * Tableview;end
Velg bordvisningen åpne Tilkoblinger Inspector
, og koble tabellen vise sin datakilden og delegere uttak til View Controller
objekt. Med tabellvisningen valgt, åpner du Egenskaper Inspector Hotell og angi antall Prototype Cells
til 1.
Før vi fortsetter, må vi opprette en UITableViewCell underklasse for prototypen cellen. Opprett en ny Objective-C underklasse, TSPToDoCell, og sette sin superklasse til UITableViewCell. Lag to utsalgssteder, nameLabel av type UILabel og doneButton av type UIButton.
Leder tilbake til dreieboken, velg prototype celle i tabellvisningen, og satt klassen TSPToDoCell i Identity Inspector
. Legg en UILabel og en UIButton objekt til cellens innhold utsikt og koble uttakene i Tilkoblinger Inspector
. Med prototypen cellen valgt, åpner du Egenskaper Inspector Hotell og sette identifikator av prototypen cellen til ToDoCell. Denne identifikatoren vil tjene som cellens gjenbruk identifikator. Prototypen cellens layout skal se omtrent slik skjermbildet nedenfor.
Opprett en ny UIViewController underklasse og kall den TSPAddToDoViewController. Erklære en stikkontakt tekstfeltet av type UITextField i visningen kontrollerens header fil og tilpasse visningen kontrolleren til UITextFieldDelegate protokollen
#import < UIKit /UIKit.h >interface TSPAddToDoViewController. UIViewController < UITextFieldDelegate >property (svak, nonatomic) IBOutlet UITextField * tekstfeltet;.end
Før vi legge til visningen kontrolleren til dreieboken, legge til følgende to handlinger til visningen kontrolleren implementering fil Anmeldelser #pragma mark - # pragma mark Actions- (IBAction) avbryte : (id) avsender {} - (IBAction) sparer: (id) avsender {}
Åpne dreieboken en gang til og legge til en bar knapp element med en identifikator for Legg
til høyre for navigeringslinjen i TSPViewController. Legg til en ny visning kontrolleren til dreieboken og sette sin klasse TSPAddToDoViewController i Identity Inspector
. Med utsikt kontrolleren valgt, velger du Embed In > Navigation Controller
fra Editor
menyen.
Den nye visningen kontrolleren skal nå ha en navigasjonsfeltet. Legg til to bar knapp elementer til navigasjonslinjen, en på venstre med en identitet for Avbryt Hotell og en på høyre med en identitet for Lagre
. Koble avbryte: action til venstre bar knappen objekt og spare. Handling til høyre bar knappen element
Legg til en UITextField objekt til visningen kontrolleren syn og plassere det 20 poeng under navigeringslinjen. Tekstfeltet skal ligge på 20 poeng under navigasjonslinjen. Merk at oppsettet begrensningen på de beste referanser toppen layout guide
, en svært praktisk tillegg som ble lagt i iOS 7.
Koble tekstfeltet med tilsvarende uttak i visningen kontrolleren og angi visningen kontrolleren som tekstfeltet delegat. Endelig kontrollere dra fra baren knappen element av TSPViewController til navigasjonskontrolleren hvorav TSPAddToDoViewController er roten view controller. Sett segue typen til modal Hotell og setter naturlig overgang identifikator til addToDoViewController i Attributter Inspector
. Det var mye å ta i Det interessante er likevel å komme skjønt
Trinn 2:.. Implementere Tabell
Før vi kan ta vår søknad om en spin, må vi iverksette den UITableViewDataSource protokoll i TSPViewController klassen. Men dette er hvor NSFetchedResultsController klassen kommer inn i bildet. For å være sikker på at alt fungerer return 0 fra Tableview: numberOfRowsInSection: metode. Dette vil resultere i en tom tabellvisning, men det vil gi oss mulighet til å kjøre programmet uten å kjøre inn i en krasj Anmeldelser - (NSInteger) Tableview: (UITableView *) Tableview numberOfRowsInSection: (NSInteger) seksjon {return 0;} <. h3> Trinn 3: Lagre & Avbryt
Åpne TSPAddToDoViewController klassen og gjennomføre de Avbryt: Klikk: metoder som vist nedenfor. . Vi vil oppdatere sine implementeringer senere i denne opplæringen
#pragma mark - # pragma mark Actions- (IBAction) avbryte: (id) avsender {//Avvis View Controller [selv dismissViewControllerAnimated: JA ferdigstillelse: null];} - (IBAction) sparer: (id) avsender {//Avvis View Controller [selv dismissViewControllerAnimated: JA ferdigstillelse: null];}
Bygg og kjøre programmet i iOS Simulator for å se om alt er koblet opp riktig. Du bør være i stand til å trykke på add-knappen øverst til høyre for å få opp TSPAddToDoViewController og avsette sistnevnte ved å tappe avbryte eller lagre knappen.
6. Implementere NSFetchedResultsController Class
NSFetchedResultsController klassen er en del av kjernedata rammeverk og det er ment å håndtere resultatene av en hente forespørsel. Klassen ble laget for å fungere sømløst med UITableView og UICollectionView på iOS og NSTableView på OS X. Men det kan brukes til andre formål også
Trinn 1:. Legging av grunn
Før vi kan begynne å jobbe med NSFetchedResultsController klassen, men de TSPViewController klassen trenger tilgang til en NSManagedObjectContext eksempel, NSManagedObjectContext eksempel vi opprettet tidligere i programmet delegat. Start med å erklære en eiendom managedObjectContext av type NSManagedObjectContext i topptekstfilen av TSPViewController klassen
#import < UIKit /UIKit.h >interface TSPViewController. UIViewController < UITableViewDataSource, UITableViewDelegate >property (svak, nonatomic) IBOutlet UITableView * Tableview,property (sterk, nonatomic) NSManagedObjectContext * managedObjectContext;end
Åpne Main.storyboard
velger dreieboken sin første visningen kontrolleren, en UINavigationController eksempel, og sette Storyboard ID
å rootNavigationController i Identity Inspector
I søknaden delegere sin søknad:. didFinishLaunchingWithOptions: metode, får vi en referanse til TSPViewController eksempel roten visning kontrolleren av navigeringskontrollen, og sette managedObjectContext eiendom. Den oppdaterte programmet: didFinishLaunchingWithOptions: metoden ser ut som følger: Anmeldelser - (BOOL) Anvendelse: (UIApplication *) applikasjons didFinishLaunchingWithOptions: (NSDictionary *) launchOptions {//Fetch Hoved Storyboard UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName: @ "Main" bundle: null]; //Instantiate Root Navigation Controller UINavigationController * rootNavigationController = (UINavigationController *) [mainStoryboard instantiateViewControllerWithIdentifier: @ "rootNavigationController"]; //Konfigurer View Controller TSPViewController * viewController = (TSPViewController *) [rootNavigationController topViewController]; if ([viewController isKindOfClass: [TSPViewController klasse]]) {[viewController setManagedObjectContext: self.managedObjectContext]; } //Konfigurer Window [self.window setRootViewController: rootNavigationController]; tilbake YES;.}
Ikke glem å legge en import regnskapet for TSPViewController klassen på toppen av TSPAppDelegate.m
For å være sikker på at alt fungerer, legger følgende log uttalelse til viewDidLoad metoden i TSPViewController klassen
#pragma mark - # pragma mark Vis Livet Cycle- (void) viewDidLoad {[super viewDidLoad].; NSLog (@ "% @", self.managedObjectContext);}
Trinn 2: Initialisering av NSFetchedResultsController Instance
Åpne gjennomføringen fil av TSPViewController klasse og erklære en egenskap av type NSFetchedResultsController i en privat klasse forlengelse . Navn eiendommen fetchedResultsController. En NSFetchedResultsController eksempel har også en delegat eiendom som trenger å samsvare med NSFetchedResultsControllerDelegate protokollen. Fordi TSPViewController eksempel vil tjene som delegat på NSFetchedResultsController eksempel, må vi tilpasse den TSPViewController klasse til NSFetchedResultsControllerDelegate protokollen som vist nedenfor
#import "TSPViewController.h" #import. ≪ CoreData /CoreData.h > @ grensesnitt TSPViewController () < NSFetchedResultsControllerDelegate >property (sterk, nonatomic) NSFetchedResultsController * fetchedResultsController;end
Det er på tide å initialisere NSFetchedResultsController eksempel. Hjertet av et usannsynlig resultater kontrolleren er den NSFetchRequest objekt, fordi den bestemmer hvilke poster de hentet resultater kontrolleren vil administrere. I visningen kontrolleren viewDidLoad metode, initial vi hente forespørsel ved å sende @ "TSPItem" til initWithEntityName: metode. Dette bør være kjent med nå, og så er neste linje der vi legger liksom beskrivelsene til hente forespørsel om å sortere resultatene basert på verdien av den createdAt egenskap av hver post.
- (Void) viewDidLoad {[super viewDidLoad ]; //Initial Fetch Request NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName: @ "TSPItem"]; //Legg Sorter Descriptors [fetchRequest setSortDescriptors: @ [[NSSortDescriptor sortDescriptorWithKey: @ "createdAt" stigende: YES]]]; //Initial Hentet Resultater Controller self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest: fetchRequest managedObjectContext: self.managedObjectContext sectionNameKeyPath: nil cacheName: null]; //Konfigurer Hentet Resultater Controller [self.fetchedResultsController setDelegate bolig:]; //Utfør Fetch NSError * error = null; [self.fetchedResultsController performFetch: & error]; if (feil) {NSLog (@ "Kan ikke utføre hente."); NSLog (@ "% @,% @", feil, error.localizedDescription); }}
initialisering av hentet resultater kontrolleren er ganske grei. Den initWithFetchRequest: managedObjectContext: sectionNameKeyPath: cacheName: metoden tar fire argumenter:
for hente forespørsel
den klarte objektet sammenheng hentet resultater kontrolleren vil følge
a § nøkkelbanen hvis du ønsker at resultatene skal bli delt opp i seksjoner
a cache navn hvis du vil aktivere caching
Vi passerer null for de to siste parametrene for nå. Det første argumentet er opplagt, men hvorfor trenger vi å passere en NSManagedObjectContext objekt også? Ikke bare er gått i forvaltet objekt sammenheng brukes til å utføre hente forespørsel, er det også greid objektet sammenheng at den hentede resultater kontrolleren vil følge for endringer. Dette vil bli klarere i løpet av få minutter når vi begynne å implementere representanten metoder for NSFetchedResultsControllerDelegate protokollen.
Til slutt må vi fortelle hentede resultater kontrolleren til å utføre hente forespørsel vi passerte den. Vi gjør dette ved å påberope performFetch: og gi det en peker til et NSError objekt. Dette ligner på executeFetchRequest: error: metoden i NSManagedObjectContext klassen
Trinn 3:. Implementering
Representant Protocol
Med hentet resultater kontrolleren satt opp og klar til bruk, må vi iverksette den NSFetchedResultsControllerDelegate protokollen. Protokollen definerer fem metoder, hvorav tre er av interesse for oss i denne tutorial:
controllerWillChangeContent:
controllerDidChangeContent:
controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
The første og andre metoder fortelle oss når dataene den hentet resultater kontrolleren er administrerende vilje og gjorde endringen. Dette er viktig for batch oppdatere brukergrensesnittet. For eksempel er det fullt mulig at flere endringer skje på samme tid. I stedet for å oppdatere brukergrensesnitt for hver endring, vi batch oppdatere brukergrensesnitt gang hver endring har blitt gjort
I vårt eksempel, koker dette ned til følgende implementeringer av controllerWillChangeContent:. Og controllerDidChangeContent :.
- (void) controllerWillChangeContent: (NSFetchedResultsController *) kontrolleren {[self.tableView beginUpdates];} - (void) controllerDidChangeContent: (NSFetchedResultsController *) kontrolleren {[self.tableView endUpdates];}
Gjennomføring av kontroller: didChangeObject: atIndexPath: forChangeType: newIndexPath: er litt mer komplisert. Denne representanten metoden tar ikke mindre enn fem argumenter:
den NSFetchedResultsController eksempel
den NSManagedObject forekomsten som endret
nåværende
indeksen banen posten i hentet resultater kontrolleren
den type endring, det vil si insert
, oppdatering
, eller slett
den nye indeksen banen til posten i hentede resultater kontrolleren, etter
endringen
Merk at indeks veier har ingenting å gjøre med vår tabellvisning. En NSIndexPath er noe mer enn et objekt som inneholder en eller flere indekser for å representere en bane i en hierarkisk struktur, derav klassen navn.
Internt hentet resultater kontrolleren styrer en hierarkisk datastruktur og den varsler sin delegat når at data strukturen endres. Det er opp til oss å visualisere disse endringene i, for eksempel, en tabellvisning
Gjennomføringen av kontrolleren. DidChangeObject: atIndexPath: forChangeType: newIndexPath: ser skremmende, men la meg gå gjennom det
. - (void) controller: (NSFetchedResultsController *) controller didChangeObject: (id) anObject atIndexPath: (NSIndexPath *) indexPath forChangeType: (NSFetchedResultsChangeType) type newIndexPath: (NSIndexPath *) newIndexPath {switch (type) {case NSFetchedResultsChangeInsert: {[selvtillit. Tableview insertRowsAtIndexPaths: [NSArray arrayWithObject: newIndexPath] withRowAnimation: UITableViewRowAnimationFade]; gå i stykker; } Tilfelle NSFetchedResultsChangeDelete: {[self.tableView deleteRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade]; gå i stykker; } Tilfelle NSFetchedResultsChangeUpdate: {[selv configureCell: (TSPToDoCell *) [self.tableView cellForRowAtIndexPath: indexPath] atIndexPath: indexPath]; gå i stykker; } Tilfelle NSFetchedResultsChangeMove: {[self.tableView deleteRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject: newIndexPath] withRowAnimation: UITableViewRowAnimationFade]; gå i stykker; }}}
Det er fire mulige endringer types:
NSFetchedResultsChangeInsert
NSFetchedResultsChangeDelete
NSFetchedResultsChangeUpdate
NSFetchedResultsChangeMove
The navnene er ganske selvforklarende. Hvis typen er NSFetchedResultsChangeInsert, vi forteller utsikten bordet for å sette inn en rad på newIndexPath. Tilsvarende, hvis typen er NSFetchedResultsChangeDelete, fjerner vi raden på indexPath fra visningen tabellen
Hvis en post er oppdatert, oppdaterer vi den tilsvarende rad i tabellvisningen ved å kalle configureCell. AtIndexPath :, en hjelper metode som godtar en UITableViewCell objekt og en NSIndexPath objekt. Vi vil implementere denne metoden i et øyeblikk.
Hvis endringen typen er lik NSFetchedResultsChangeMove, fjerner vi raden på indexPath og sette inn en rad på newIndexPath å reflektere posten oppdaterte posisjon i hentet resultater kontrollerens interne data struktur
Trinn 4:. Implementering
UITableViewDataSource Protocol
Det var ikke så vanskelig. Var det? Implementere UITableViewDataSource protokollen er mye enklere, men det er et par ting du bør være klar over. La oss starte med numberOfSectionsInTableView: og Tableview: numberOfRowsInSection. Metoder
Selv om tabellvisning i vår prøveprogrammet vil bare ha én del, la oss be hentet resultater kontrolleren for antall seksjoner. Vi gjør dette ved å kalle deler på den, som returnerer en matrise av objekter som er i samsvar med NSFetchedResultsSectionInfo protokollen.
Objekter i samsvar med gjeldende NSFetchedResultsSectionInfo protokollen trenger for å implementere noen metoder, inkludert numberOfObjects. Dette gir oss det vi trenger for å gjennomføre de to første metodene for UITableViewDataSource protokollen Anmeldelser - (NSInteger) numberOfSectionsInTableView: (UITableView *) Tableview {return [[self.fetchedResultsController seksjoner] telle];} - (NSInteger) Tableview.: (UITableView *) Tableview numberOfRowsInSection: (NSInteger) section {NSArray * seksjoner = [self.fetchedResultsController seksjoner]; id < NSFetchedResultsSectionInfo > sectionInfo = [seksjoner objectAtIndex: seksjonen]; tilbake [sectionInfo numberOfObjects];}
Neste er opp Tableview: cellForRowAtIndexPath: og configureCell: atIndexPath: metoder. Begynn med å legge en import statement for overskriften på TSPToDoCell klassen
#import "TSPToDoCell.h"
Gjennomføringen av Tableview. CellForRowAtIndexPath: er kort, fordi vi flytte det meste av cellens konfigurasjonen til configureCell: atIndexPath: . Vi ber tabellvisningen for en gjenbrukbar celle med gjenbruk identifikator @ "ToDoCell" og passerer cellen og indeksen banen til configureCell: atIndexPath :. Anmeldelser - (UITableViewCell *) Tableview: (UITableView *) Tableview cellForRowAtIndexPath: (NSIndexPath * ) indexPath {TSPToDoCell * celle = (TSPToDoCell *) [Tableview dequeueReusableCellWithIdentifier: @ "ToDoCell" forIndexPath: indexPath]; //Konfigurer Tabell Cell [selv configureCell: cell atIndexPath: indexPath]; returnere celle;}
Magien skjer i configureCell: atIndexPath :. Vi ber hentet resultater kontrolleren for varen ved indexPath. Den hentet resultater kontrolleren returnerer en NSManagedObject eksempel til oss. Vi oppdaterer nameLabel og tilstanden i doneButton ved å spørre rekorden for sitt navn og done attributter Anmeldelser - (void) configureCell:. (TSPToDoCell *) celle atIndexPath: (NSIndexPath *) indexPath {//Fetch Record NSManagedObject * rekord = [self.fetchedResultsController objectAtIndexPath: indexPath]; //Update Cell [cell.nameLabel setText: [rekord valueForKey: @ "navn"]]; [cell.doneButton setSelected: [[rekord valueForKey: @ "ferdig"] boolValue]];}
Vi vil revidere UITableViewDataSource protokollen senere i denne opplæringen når vi slette elementer fra listen. Må vi først fylle tabellvisning med noen data.
7. Legge Records
La oss avslutte denne opplæringen ved å legge muligheten til å skape gjøremål. Åpne TSPAddToDoViewController klassen, legge en import statement for Core data rammeverket, og erklære en eiendom managedObjectContext av type NSManagedObjectContext
#import. ≪ UIKit /UIKit.h > #import < CoreData /CoreData.h >interface TSPAddToDoViewController : UIViewController < UITextFieldDelegate >property (svak, nonatomic) IBOutlet UITextField * Textfield,property (sterk, nonatomic) NSManagedObjectContext * managedObjectContext;end
Leder tilbake til TSPViewController klassen og implementere prepareForSegue: avsender: metode. I denne metoden, setter vi managedObjectContext eiendommen av TSPAddToDoViewController eksempel. Hvis du har jobbet med storyboards før, da gjennomføringen av prepareForSegue: avsender: bør være grei Anmeldelser - (void) prepareForSegue:. (UIStoryboardSegue *) segue avsender: (id) avsender {if ([segue.identifier isEqualToString: @ "addToDoViewController"]) {//Skaff Henvisning til View Controller UINavigationController * nc = (UINavigationController *) [naturlig overgang destinationViewController]; TSPAddToDoViewController * vc = (TSPAddToDoViewController *) [nc topViewController]; //Konfigurer View Controller [vc setManagedObjectContext: self.managedObjectContext]; }}
Hvis brukeren skriver inn tekst i tekstfeltet i TSPAddToDoViewController og kraner Lagre
knappen, skaper vi en ny rekord, fylle den med data, og lagre det. Denne logikken går inn på lagre: metode vi opprettet tidligere Anmeldelser - (IBAction) sparer:. (Id) avsender {//Hjelpere NSString * name = self.textField.text; if (navn & & name.length) {//Lag Entity NSEntityDescription * enhet = [NSEntityDescription entityForName: @ "TSPItem" inManagedObjectContext: self.managedObjectContext]; //Initial Record NSManagedObject * record = [[NSManagedObject alloc] initWithEntity: enhet insertIntoManagedObjectContext: self.managedObjectContext]; //Befolke Record [rekord SetValue: name Forkey: @ "navn"]; [rekord SetValue: [NSDate dato] Forkey: @ "createdAt"]; //Lagre post NSError * error = null; if ([self.managedObjectContext sparer: & error]) {//Avvis View Controller [selv dismissViewControllerAnimated: JA ferdigstillelse: null]; } Else {if (feil) {NSLog (@ "Kan ikke lagre posten."); NSLog (@ "% @,% @", feil, error.localizedDescription); } //Show Alert Se [[[UIAlertView alloc] initWithTitle: "Advarsel" -melding @: @ "to-do kunne ikke lagres." delegat: nil cancelButtonTitle: @ "OK" otherButtonTitles: null] showet]; }} Else {//Show Alert Se [[[UIAlertView alloc] initWithTitle: @ "Warning" budskap: ". Din gjøremål trenger et navn" @ delegat: nil cancelButtonTitle: @ "OK" otherButtonTitles: null] showet]; }}
spare: metode ser ganske imponerende, men det er ingenting i det som vi ikke har dekket ennå. Vi skaper en ny administrert objekt ved å bestå en NSEntityDescription forekomst og en NSManagedObjectContext eksempel. Vi deretter fylle klarte objekt med et navn og dato. Hvis du lagrer klarte objektet sammenheng er vellykket, vi avviser visningen kontrolleren, ellers viser vi et varsel visning.