iOS 8: kjernedata og Batch oppdateringer
22
Del
4
Del
Dette Cyber Monday 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:. ConcurrencyiOS 8: kjernedata og Asynchronous Henter
Kjerne Data har eksistert i mange år på OS X og det tok ikke Apple lang tid å bringe den til iOS. Selv om rammen ikke får så mye oppmerksomhet som utvidelser eller omruting, fortsetter det å utvikle seg år over år, og i år, med utgivelsen av iOS 8 og OS X Yosemite, er ikke annerledes.
Apple introdusert et par nye funksjoner til kjernen data rammeverk, men det mest bemerkelsesverdige er batch oppdateringer og asynkron henting. Utviklere har spurt etter disse funksjonene i mange år og Apple endelig funnet en måte å integrere dem i kjernedata. I denne opplæringen vil jeg vise deg hvordan batch oppdateringer fungerer og hva de betyr for Core data rammeverket.
1. Problemet
Kjerne data er gode på å håndtere objekt grafer. Selv komplekse objekt grafer med mange enheter og relasjoner er ikke mye av et problem for kjernedata. Men gjør kjernedata har noen svake punkter og oppdatering av et stort antall poster er en av dem.
Problemet er lett å forstå. Når du oppdaterer en post, laster kjernedata posten inn i minnet, oppdaterer posten, og lagre endringene i den vedvarende butikken, en SQLite database for eksempel.
Hvis kjernedata må oppdatere et stort antall poster , det er behov for å laste hver enkelt post i minnet, oppdatere posten, og sende endringene til den vedvarende butikken. Hvis antall poster er for stor, vil iOS bare kausjon ut på grunn av manglende ressurser. Selv om en enhet som kjører OS X kan ha ressurser til å gjennomføre anmodningen, vil det være treg og bruker mye minne.
En alternativ tilnærming er å oppdatere postene i grupper, men som også tar mye av tid og ressurser. På iOS 7, det er det eneste alternativet iOS utviklere har. Det er ikke lenger tilfelle på iOS 8.
2. Løsningen
På iOS 8 og OS X Yosemite, er det mulig å snakke direkte til den vedvarende butikken og fortelle den hva du ønsker å endre. Dette innebærer vanligvis å oppdatere et attributt eller slette en rekke poster. Apple kaller denne funksjonen batch oppdateringer.
Det finnes en rekke fallgruver å se opp for skjønt. Kjernen data gjør en masse ting for deg og du kan ikke engang klar over det før du bruker batch oppdateringer. Validering er et godt eksempel. Fordi kjernedata utfører batch oppdateringer direkte på vedvarende butikken, for eksempel en SQLite database, er kjernedata ikke er i stand til å utføre noen undersøkelser på data du setter inn. Dette betyr at du er ansvarlig for å sørge for at du ikke legger til ugyldige data til den vedvarende butikken.
Når vil du bruke batch oppdateringer? Apple anbefaler å bare bruke denne funksjonen hvis den tradisjonelle tilnærmingen er for ressurs eller tidkrevende. Hvis du trenger å markere hundrevis eller tusenvis av e-postmeldinger som lest, så batch oppdateringer er den beste løsningen på iOS 8 og OS X Yosemite.
3. Hvordan virker det?
For å illustrere hvordan batch oppdateringer fungerer, foreslår jeg at vi besøker Ferdig, en enkel kjernedata program som styrer en to-do liste. Vi vil legge til en knapp navigasjonsfeltet som markerer hvert element i listen som gjøres
Trinn 1:. Projet Setup
Last ned eller klone prosjektet fra GitHub og åpne den i Xcode 6 . Kjør programmet i iOS Simulator og tilsett noen gjøremål
Trinn 2:. Lag Bar Button Varen
Åpne TSPViewController.m Hotell og erklære en eiendom , checkAllButton, av type UIBarButtonItem i privat klasse forlengelse på toppen
interface TSPViewController (). < NSFetchedResultsControllerDelegate >property (sterk, nonatomic) NSFetchedResultsController * fetchedResultsController;property (sterk, nonatomic) UIBarButtonItem * checkAllButton;property (sterk, nonatomic) NSIndexPath * valg;end
Initial baren knappen elementet i viewDidLoad metoden i TSPViewController klassen og sette den som venstre bar knappen element av navigasjons varen checkAll: Metoden er ganske lett, men det er et par ting å se opp for. Ta en titt på gjennomføringen under Anmeldelser - (void) checkAll: (id) avsender {//Opprett Entity Beskrivelse NSEntityDescription * entityDescription = [NSEntityDescription entityForName: @ "TSPItem" inManagedObjectContext: self.managedObjectContext].; //Initial Batch Update Request NSBatchUpdateRequest * batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity: entityDescription]; //Konfigurer Batch Update Request [batchUpdateRequest setResultType: NSUpdatedObjectIDsResultType]; [batchUpdateRequest setPropertiesToUpdate: @ {@ "ferdig":YES}]; //Execute Batch Request NSError * batchUpdateRequestError = null; NSBatchUpdateResult * batchUpdateResult = (NSBatchUpdateResult *) [self.managedObjectContext executeRequest: batchUpdateRequest error: & batchUpdateRequestError]; if (batchUpdateRequestError) {NSLog (@ "Kan ikke kjøre batch oppdatering forespørsel."); NSLog (@ "% @,% @", batchUpdateRequestError, batchUpdateRequestError.localizedDescription); } Else {//Extract Object IDer NSArray * objectIDs = batchUpdateResult.result; for (NSManagedObjectID * objectID i objectIDs) {//Ta Managed Objects inn feil NSManagedObject * managedObject = [self.managedObjectContext objectWithID: objectID]; if (managedObject) {[self.managedObjectContext refreshObject: managedObject mergeChanges: NO]; }} //Utfør Fetch NSError * fetchError = null; [self.fetchedResultsController performFetch: & fetchError]; if (fetchError) {NSLog (@ "Kan ikke utføre hente."); NSLog (@ "% @,% @", fetchError, fetchError.localizedDescription); }}} Vi starter ved å opprette en NSEntityDescription eksempel for TSPItem Vi setter resultatet type batch oppdatering forespørsel til NSUpdatedObjectIDsResultType, noe som betyr at resultatet av batch oppdatere forespørsel vil være en matrise som inneholder objekt IDer, forekomster av NSManagedObjectID klassen, av postene som ble endret ved batch oppdateringen forespørsel. Vi fyller også propertiesToUpdate eiendommen av batch oppdateringen forespørsel. For dette eksempelet setter vi propertiesToUpdate til en NSDictionary inneholder en nøkkel, @ "ferdig", med verdiYES. Dette betyr ganske enkelt at hver TSPItem Selv om batch oppdateringer omgå klarte objektet sammenheng, gjennomføre en batch oppdatering anmodning gjøres ved å ringe executeRequest: error: på en NSManagedObjectContext eksempel. Det første argumentet er en forekomst av NSPersistentStoreRequest klassen. For å utføre en batch oppdatering, passerer vi batch oppdateringen forespørsel om vi nettopp opprettet. Dette fungerer finnene siden NSBatchUpdateRequest klassen er en NSPersistentStoreRequest underklasse. Det andre argumentet er en peker til et NSError objekt Som jeg nevnte tidligere, batch oppdateringer omgå klarte objektet sammenheng. Dette gir batch oppdateringer sin kraft og fart, men det betyr også at den klarte objektet sammenheng er ikke klar over de endringene vi har gjort. For å bøte på dette problemet, må vi gjøre to ting: Dette er hva vi gjør i de neste par linjene i checkAll: metode. Vi sjekker først om batch oppdatere forespørselen var vellykket ved å sjekke batchUpdateRequestError for null. Hvis de lykkes, trekke vi rekken av NSManagedObjectID tilfeller fra NSBatchUpdateResult objektet Vi iterere over objectIDs matrise og be klarte objektet kontekst for den tilsvarende NSManagedObject instans. Hvis klarte objektet sammenheng returnerer en gyldig klarte objekt, vi gjøre det til en feil ved å påberope refreshObject: mergeChanges :, bestått i forvaltet objekt som første argument. For å tvinge klarte objekt i en feil, passerer vi INGEN som andre argument Det siste trinnet er å fortelle hentede resultater kontrolleren til å utføre en hente å oppdatere brukergrensesnitt. Hvis dette ikke lykkes, kan du logge vi den tilsvarende feil Selv om dette kan virke tungvint og ganske komplisert for en enkel operasjon, husk at vi omgå kjernedata stabelen. Med andre ord, må vi ta vare på noen housekeeping som vanligvis gjort for oss av kjernedata Bygg prosjektet og kjøre programmet på iOS Simulator eller på en fysisk enhet. Klikk eller trykk på bar-knappen elementet til høyre for å sjekke hver gjøremål element i listen. Batch oppdateringer er et flott tillegg til Core data rammeverket. Ikke bare svare på et behov utviklerne har hatt i mange år, er det ikke vanskelig å gjennomføre så lenge du holde et par grunnleggende regler i tankene. I neste opplæringen, vil vi ta en nærmere titt på asynkron henting, en annen ny funksjon av grunndata rammeverket.
Trinn 3: Gjennomføre checkAll: Metode
Opprett Batch Request
enhet og bruke den til å klargjøre en NSBatchUpdateRequest objekt.
//Lag Entity DescriptionNSEntityDescription * entityDescription = [NSEntityDescription entityForName: @ "TSPItem" inManagedObjectContext: self.managedObjectContext]; //Initial Batch Update RequestNSBatchUpdateRequest * batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity: entityDescription];
//Konfigurer Batch Update Request [batchUpdateRequest setResultType: NSUpdatedObjectIDsResultType];
posten vil bli satt til gjort
, som er akkurat det vi ønsker
//Konfigurer Batch Update Request [batchUpdateRequest setPropertiesToUpdate:. @ {@ "Ferdig ":YES}]; Kjør Batch Update Request
//Execute Batch RequestNSError * batchUpdateRequestError = null; NSBatchUpdateResult * batchUpdateResult = (NSBatchUpdateResult *). [Self.managedObjectContext executeRequest: batchUpdateRequest error: & batchUpdateRequestError]; Oppdatering Managed Object Context
slå de administrerte objekter som ble oppdatert via batch oppdateringen i feil
fortelle hentet resultater kontrolleren til å utføre en hente til oppdatere brukergrensesnitt
//Extract Object IDsNSArray * objectIDs = batchUpdateResult.result;.
//Extract Object IDsNSArray * objectIDs = batchUpdateResult.result;. For (NSManagedObjectID * objectID i objectIDs) {//Ta Managed Objects inn feil NSManagedObject * managedObject = [self.managedObjectContext objectWithID: objectID]; if (managedObject) {[self.managedObjectContext refreshObject: managedObject mergeChanges: NO]; }} Henter Oppdatert Records
//Utfør FetchNSError * fetchError = null; [self.fetchedResultsController performFetch: & fetchError];. If (fetchError) {NSLog (@ ". Kan ikke utføre hente"); NSLog (@ "% @,% @", fetchError, fetchError.localizedDescription);}
Trinn 4:. Bygg & Kjør
Konklusjon