Kjernen data fra Scratch: Mer NSFetchedResultsController

Core data fra Scratch: Mer NSFetchedResultsController
24
Del
Del
Del
Dette Cyber ​​mandag Envato Tuts + kurs 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:. NSFetchedResultsControllerCore data fra Scratch: Migrations

I denne opplæringen, vi fortsetter vår utforskning av NSFetchedResultsController klassen ved å legge muligheten til å oppdatere og slette gjøremål. Du vil merke at oppdatering og sletting gjøremål er overraskende enkel takket være grunnlaget vi lagt i forrige tutorial.

1. Oppdatere en Record navn

Trinn 1: Lag View Controller

Start med å lage en ny UIViewController underklasse heter TSPUpdateToDoViewController. I TSPUpdateToDoViewController.h
, erklærer en stikkontakt, Textfield av type UITextField, og to eiendommer, managedObjectContext av type NSManagedObjectContext og registrering av typen NSManagedObject. Legg en import statement for Core data rammeverket på toppen
#import < UIKit /UIKit.h > #import < CoreData /CoreData.h >interface TSPUpdateToDoViewController. UIViewController @ eiendom (svak, nonatomic) IBOutlet UITextField * Textfield,property (sterk, nonatomic) NSManagedObjectContext * managedObjectContext;property (sterk, nonatomic) NSManagedObject * record;end

I visningen kontrolleren implementering fil, TSPUpdateToDoViewController.m
, lage to handlinger , avbryter: og lagre :. Sine implementeringer kan forbli tom for tiden
#import "TSPUpdateToDoViewController.h"@implementation TSPUpdateToDoViewController # pragma mark - # pragma mark Actions- (IBAction) avbryte:. (Id) avsender {} - (IBAction) spare :( id) avsender {}end
Trinn 2: Oppdatering Storyboard

Åpne hovedstoryboard, Main.storyboard
, legge til en ny visning controller objekt, og sette sin klasse TSPUpdateToDoViewController i Identity Inspector
. Lag en manuell naturlig overgang fra TSPViewController klasse til TSPUpdateToDoViewController klassen. I attributter Inspector
, setter naturlig overgang stil til trykk Hotell og sin identifikator til updateToDoViewController.

Legg til en UITextField objekt til visningen av TSPUpdateToDoViewController objektet og konfigurere det bare som vi gjorde med tekstfeltet i TSPAddToDoViewController klassen. Ikke glem å koble visningen kontrollerens stikkontakt med tekstfeltet.

Som i TSPAddToDoViewController klassen, tilsett to bar knapp elementer til visningen kontrolleren navigasjonsfeltet, setter sin identitet til Avbryt Anmeldelser og Lagre
henholdsvis, og koble hver bar knappen element til tilsvarende tiltak i Tilkoblinger Inspector

Trinn 3:. Passerer en Reference

trenger også å gjøre noen endringer i TSPViewController klassen. Legg en import regnskapet for TSPUpdateToDoViewController klasse på toppen og erklære en eiendom som heter valg av type NSIndexPath til privat klasse forlengelse i TSPViewController.m
#import "TSPViewController.h" #import <.; CoreData /CoreData.h > #import "TSPToDoCell.h" #import "TSPAddToDoViewController.h" #import "TSPUpdateToDoViewController.h"@interface TSPViewController () < NSFetchedResultsControllerDelegate >property (sterk, nonatomic) NSFetchedResultsController * fetchedResultsController;property ( sterk, nonatomic) NSIndexPath * valg;end

Deretter implementere Tableview: didSelectRowAtIndexPath: metoden i UITableViewDelegate protokollen. I denne metoden, vi midlertidig lagre brukerens valg i utvelgelsen eiendom
#pragma mark - # pragma mark Tabell Deleger Methods- (void) Tableview:. (UITableView *) Tableview didSelectRowAtIndexPath: (NSIndexPath *) indexPath {[Tableview deselectRowAtIndexPath: indexPath animerte: YES]; //Butikk Selection [selv setSelection: indexPath];}

I klassens prepareForSegue: avsender :, vi hente posten som korresponderer med brukerens valg og gi det til TSPUpdateToDoViewController eksempel. For å forhindre uventet oppførsel, vi bare utføre dette trinnet hvis valget er ikke null, og nullstill utvalg eiendommen etter å hente posten fra usannsynlig resultater controller 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]; } Else if ([segue.identifier isEqualToString: @ "updateToDoViewController"]) {//Skaff Henvisning til View Controller TSPUpdateToDoViewController * vc = (TSPUpdateToDoViewController *) [naturlig overgang destinationViewController]; //Konfigurer View Controller [vc setManagedObjectContext: self.managedObjectContext]; if (self.selection) {//Fetch Record NSManagedObject * record = [self.fetchedResultsController objectAtIndexPath: self.selection]; if (rekord) {[vc setRecord: record]; } //Tilbake Selection [selv setSelection: null]; }}}
Trinn 4:. Fyller tekstfeltet

I viewDidLoad metoden i TSPUpdateToDoViewController klassen, fylle ut tekstfelt med navnet på den posten som vist nedenfor Anmeldelser #pragma mark - # Pragma mark Vis Livet Cycle- (void) viewDidLoad {[super viewDidLoad]; if (self.record) {//Update Text Feltet [self.textField setText: [self.record valueForKey: @ "navn"]]; }}
Trinn 5: Oppdatere Record

I avbryte. handling, pop vi oppdateringen view controller fra navigasjonskontrolleren navigasjon stack Anmeldelser - (IBAction) avbryte: (id) avsender { //Pop View Controller [self.navigationController popViewControllerAnimated: YES];}

I spare: action, vi først sjekke om tekstfeltet er tomt, og viser et varsel utsikt hvis det er. Hvis tekstfeltet inneholder en gyldig verdi, oppdaterer vi rekord navn attributt og pop utsikten kontrolleren fra navigasjonskontrolleren navigasjon stack Anmeldelser - (IBAction) sparer:. (Id) avsender {//Hjelpere NSString * name = selvtillit. textField.text; if (navn & & name.length) {//Befolke Record [self.record SetValue: navn Forkey: @ "navn"]; //Lagre post NSError * error = null; if ([self.managedObjectContext sparer: & error]) {//Pop View Controller [self.navigationController popViewControllerAnimated: YES]; } 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]; }}

Dette er alt som trengs for å oppdatere en post ved hjelp av kjernedata. Kjøre programmet en gang til og se om alt fungerer. Den hentet resultater kontrolleren oppdager automatisk endringen og varsler sin representant, TSPViewController eksempel. Den TSPViewController objekt, på sin side, oppdaterer tabellen sikte på å gjenspeile endringen. Så enkelt er det.

2. Oppdatere en rekord statens

Trinn 1: Oppdatere TSPToDoCell

Når en bruker kraner på knappen på høyre side av en TSPToDoCell, må varens tilstand å endre. For å oppnå dette, må vi først å oppdatere TSPToDoCell klassen. Åpne TSPToDoCell.m Hotell og legge en typedef for en blokk som heter TSPToDoCellDidTapButtonBlock. Deretter erklærer en egenskap av type TSPToDoCellDidTapButtonBlock og sørge for at eiendommen blir kopiert på oppdrag
#import < UIKit /UIKit.h > typedef void (^ TSPToDoCellDidTapButtonBlock) (); @ grensesnitt TSPToDoCell. UITableViewCell @ eiendom (svak, nonatomic) IBOutlet UILabel * nameLabel;property (svak, nonatomic) IBOutlet UIButton * doneButton;property (kopi, nonatomic) TSPToDoCellDidTapButtonBlock didTapButtonBlock;end

Leder for klassen implementering fil, TSPToDoCell.m Anmeldelser og påberope setupView, en hjelper metode, i awakeFromNib
#pragma mark - # pragma mark Initialization- (void) awakeFromNib {[super awakeFromNib].; //Setup Se [selvtillit setupView];}

I setupView, konfigurere vi doneButton objekt ved å sette bilder for hver stat på knappen og legge tabellvisningen celle som et mål. Når brukeren kraner på knappen, blir tabellvisning cellen sendte en melding av didTapButton: der påberope vi didTapButtonBlock blokken. Du vil se i et øyeblikk hvor praktisk dette mønsteret er. Bildene inngår i kildefilene for denne opplæringen, som du kan finne på GitHub
#pragma mark - # pragma mark Vis Methods- (void) setupView {UIImage * imageNormal = [UIImage imageNamed:. @ "-knappen-Done -normal"]; UIImage * imageSelected = [UIImage imageNamed: @ "button-gjort-valgt"]; [self.doneButton setImage: imageNormal forState: UIControlStateNormal]; [self.doneButton setImage: imageNormal forState: UIControlStateDisabled]; [self.doneButton setImage: imageSelected forState: UIControlStateSelected]; [self.doneButton setImage: imageSelected forState: UIControlStateHighlighted]; [self.doneButton addTarget: selv handling:selector (didTapButton :) forControlEvents: UIControlEventTouchUpInside];} # pragma mark - # pragma mark Actions- (void) didTapButton: (UIButton *) knappen {if (self.didTapButtonBlock) {selv. didTapButtonBlock (); }}
Trinn 2: Oppdatere TSPViewController

Takk til NSFetchedResultsController klassen og grunnlaget vi har lagt, vi trenger bare å oppdatere configureCell: atIndexPath: metoden i TSPViewController klassen Anmeldelser - (. void) configureCell: (TSPToDoCell *) celle atIndexPath: (NSIndexPath *) indexPath {//Fetch Record NSManagedObject * record = [self.fetchedResultsController objectAtIndexPath: indexPath]; //Update Cell [cell.nameLabel setText: [rekord valueForKey: @ "navn"]]; [cell.doneButton setSelected: [[rekord valueForKey: @ "ferdig"] boolValue]]; [celle setDidTapButtonBlock: ^ {BOOL isdone = [[rekord valueForKey: @ "ferdig"] boolValue]; //Update Record [rekord SetValue: @ Forkey (isdone!): @ "Ferdig"]; }];}
Trinn 3: Saving Changes

Du lurer kanskje på hvorfor vi ikke er redde klarte objektet sammenheng. Vil ikke vi mister de endringene vi har gjort hvis vi ikke forplikte endringene i den vedvarende butikken? Ja og nei.

Det er sant at vi trenger å skrive endringene av den administrerte objektet sammenheng til backing butikken på enkelte punkt. Hvis vi ikke gjør det, vil brukeren miste noen av sine data. Men det er ikke nødvendig å lagre endringene av en administrert objekt sammenheng hver gang vi gjør en endring.

En bedre tilnærming er å redde klarte objektet sammenheng øyeblikket programmet flyttes til bakgrunnen. Vi kan gjøre dette i applicationDidEnterBackground: metoden i UIApplicationDelegate protokollen. . Åpne TSPAppDelegate.m Hotell og implementere applicationDidEnterBackground: som vist nedenfor Anmeldelser - (void) applicationDidEnterBackground: (UIApplication *) søknad {NSError * error = null; if (! [self.managedObjectContext sparer: & error]) {if (feil) {NSLog (@ "Kan ikke lagre endringene."); NSLog (@ "% @,% @", feil, error.localizedDescription); }}}

Men dette fungerer ikke hvis søknaden er Tvungen avslutning av brukeren. Det er derfor en god idé å også lagre klarte objektet sammenheng når programmet avsluttes. Den applicationWillTerminate: Metoden er en annen metode for den UIApplicationDelegate protokoll som varsler application't delegat når programmet er i ferd med å bli avsluttet Anmeldelser - (void) applicationWillTerminate: (UIApplication *) søknad {NSError * error = null;. if (! [self.managedObjectContext sparer: & error]) {if (feil) {NSLog (@ "Kan ikke lagre endringene."); NSLog (@ "% @,% @", feil, error.localizedDescription); }}}

Merk at vi har duplisert kode i applicationDidEnterBackground: og applicationWillTerminate :. Det er derfor en god idé å lage en hjelper metode for å lagre klarte objektet sammenheng og kaller dette helper metoden i både delegat metoder Anmeldelser #pragma mark - # pragma mark Helper Methods- (void) saveManagedObjectContext {NSError * error = null.; if (! [self.managedObjectContext sparer: & error]) {if (feil) {NSLog (@ "Kan ikke lagre endringene."); NSLog (@ "% @,% @", feil, error.localizedDescription); }}}
3. Slette Records

Du vil bli overrasket over hvor enkelt det er å slette poster som bruker NSFetchedResultsController klassen. Start med å implementere Tableview: canEditRowAtIndexPath: metoden i UITableViewDataSource protokollen Anmeldelser - (BOOL) Tableview: (UITableView *) Tableview canEditRowAtIndexPath: (NSIndexPath *) indexPath {return JA;}

Den andre metoden for UITableViewDataSource protokollen. at vi må implementere er Tableview: commitEditingStyle: forRowAtIndexPath :. I denne metoden vi hente klarte objekt brukeren har valgt for sletting, og gi det til deleteObject: metode for den klarte objekt sammenheng med den hentet resultater controller Anmeldelser - (void) Tableview:. (UITableView *) Tableview commitEditingStyle :( UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {NSManagedObject * record = [self.fetchedResultsController objectAtIndexPath: indexPath]; if (rekord) {[self.fetchedResultsController.managedObjectContext deleteObject: record]; }}}

Fordi vi allerede har implementert NSFetchedResultsControllerDelegate protokollen, er brukergrensesnittet automatisk oppdatert, animasjoner inkludert.

Konklusjon

Jeg håper du enig i at det NSFetchedResultsController klasse er en veldig praktisk medlem av Core data rammeverket. Hvis du forstår det grunnleggende kjernedata rammeverk, så er det ikke vanskelig å få opp til hastighet med denne klassen. Jeg oppfordrer deg til å utforske videre sin API for å finne ut hva annet det kan gjøre for deg.