iOS 8 kerngegevens en asynchroon ophalen

In het vorige artikel over iOS 8 en Core Data hebben we batch-updates besproken. Batch-updates zijn niet de enige nieuwe API in de stad. Vanaf iOS 8 en OS X Yosemite is het mogelijk om asynchroon gegevens op te halen. In deze zelfstudie gaan we dieper in op het implementeren van asynchroon ophalen en in welke situaties uw toepassing kan profiteren van deze nieuwe API.

1. Het probleem

Net als batchupdates staat asynchroon ophalen al geruime tijd op het verlanglijstje van veel ontwikkelaars. Ophaalopdrachten kunnen ingewikkeld zijn en het kost een niet-triviale hoeveelheid tijd om te voltooien. Gedurende die tijd blokkeert het ophaalverzoek de thread waarop het wordt uitgevoerd en blokkeert als gevolg de toegang tot de context van het beheerde object dat de ophaalopdracht uitvoert. Het probleem is eenvoudig te begrijpen, maar hoe ziet de oplossing van Apple eruit.

2. De oplossing

Het antwoord van Apple op dit probleem is asynchroon ophalen. Een asynchrone ophaalopdracht wordt op de achtergrond uitgevoerd. Dit betekent dat het andere taken niet blokkeert terwijl het wordt uitgevoerd, zoals het bijwerken van de gebruikersinterface op de hoofdthread.

Asynchroon ophalen heeft ook twee andere handige functies, voortgangsrapportage en annulering. Een asynchroon ophaalverzoek kan op elk moment worden geannuleerd, bijvoorbeeld wanneer de gebruiker beslist dat het ophaalverzoek te lang duurt om te voltooien. Voortgangsrapportage is een nuttige toevoeging om de gebruiker de huidige status van het ophaalverzoek te tonen.

Asynchroon ophalen is een flexibele API. Niet alleen is het mogelijk om een ​​asynchrone ophaalopdracht te annuleren, het is ook mogelijk om wijzigingen aan te brengen in de context van het beheerde object terwijl de asynchrone ophaalopdracht wordt uitgevoerd. Met andere woorden, de gebruiker kan uw toepassing blijven gebruiken terwijl de toepassing op de achtergrond een asynchroon ophaalverzoek uitvoert.

3. Hoe werkt het??

Net als batchupdates worden asynchrone ophaalopdrachten als context aan de beheerde objectcontext gegeven NSPersistentStoreRequest object, een instantie van de NSAsynchronousFetchRequest Klasse om precies te zijn.

Een NSAsynchronousFetchRequest instantie wordt geïnitialiseerd met een NSFetchRequest object en een voltooiingsblok. Het voltooiingsblok wordt uitgevoerd wanneer de asynchrone ophaalopdracht zijn ophaalverzoek heeft voltooid.

Laten we de taak opnieuw bekijken die we eerder in deze serie hebben gemaakt en de huidige implementatie van de NSFetchedResultsController klasse met een asynchrone ophaalopdracht.

Stap 1: Projectinstellingen

Download of kloont het project vanuit GitHub en open het in Xcode 6. Voordat we kunnen gaan werken met de NSAsynchronousFetchRequest klas, moeten we een paar wijzigingen aanbrengen. We zullen de. Niet kunnen gebruiken NSFetchedResultsController klasse voor het beheren van de gegevens van de tabelweergave sinds de NSFetchedResultsController klasse is ontworpen om op de hoofdthread te draaien.

Stap 2: De opgehaalde resultatencontroller vervangen

Begin met het bijwerken van de privéklasse-extensie van de TSPViewController klasse zoals hieronder getoond. We verwijderen de fetchedResultsController eigendom en creëer een nieuwe eigenschap, items, van type NSArray voor het opslaan van de taken. Dit betekent ook dat de TSPViewController klasse hoeft niet langer te voldoen aan de NSFetchedResultsControllerDelegate protocol.

@interface TSPViewController () @property (strong, nonatomic) NSArray * items; @eigenschap (sterk, niet-atomisch) NSIndexPath * selectie; @einde

Voordat we refactor de viewDidLoad methode, wil ik eerst de implementatie van de UITableViewDataSource protocol. Bekijk de wijzigingen die ik heb aangebracht in de volgende codeblokken.

- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.items? 1: 0; 
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) sectie return self.items? self.items.count: 0; 
- (void) configureCell: (TSPToDoCell *) cel atIndexPath: (NSIndexPath *) indexPath // Fetch Record NSManagedObject * record = [self.items objectAtIndex: indexPath.row]; // Update Cell [cell.nameLabel setText: [recordwaardeForKey: @ "name"]]; [cel.doneButton setSelected: [[record valueForKey: @ "done"] boolValue]]; [cell setDidTapButtonBlock: ^ BOOL isDone = [[record valueForKey: @ "done"] boolValue]; // Update Record [record setValue: @ (! IsDone) forKey: @ "done"]; ]; 
- (void) tableView: (UITableView *) tableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath if (editingStyle == UITableViewCellEditingStyleDelete) NSManagedObject * record = [self.items objectAtIndex: indexPath.row]; if (record) [self.managedObjectContext deleteObject: record]; 

We moeten ook een regel code wijzigen in de prepareForSegue: afzender: methode zoals hieronder getoond.

// Fetch Record NSManagedObject * record = [self.items objectAtIndex: self.selection.row];

Last but not least, verwijder de implementatie van de NSFetchedResultsControllerDelegate protocol omdat we het niet langer nodig hebben.

Stap 3: Het maken van de asynchrone ophaalopdracht

Zoals je hieronder kunt zien, maken we de asynchrone ophaalopdracht in de view-controller's viewDidLoad methode. Laten we een moment nemen om te zien wat er aan de hand is.

- (void) viewDidLoad [super viewDidLoad]; // Helpers __weak TSPViewController * weakSelf = self; // Initialize Fetch Request NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName: @ "TSPItem"]; // Sorteerbeschrijvingen toevoegen [fetchRequest setSortDescriptors: @ [[NSSortDescriptor sortDescriptorWithKey: @ "createdAt" oplopend: YES]]]; // Asynchrone ophaalopdracht initialiseren NSAsynchronousFetchRequest * asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest: fetchRequest completionBlock: ^ (NSAsynchronousFetchResult * result) dispatch_async (dispatch_get_main_queue (), ^ // Asynchroon ophaalresultaat verwerken [weakSelf processAsynchronousFetchResult: result];) ; ]; // Asynchrone ophaalopdracht uitvoeren [self.managedObjectContext performBlock: ^ // Asynchrone ophaalopdracht uitvoeren NSError * asynchronousFetchRequestError = nil; NSAsynchronousFetchResult * asynchronousFetchResult = (NSAsynchronousFetchResult *) [weakSelf.managedObjectContext executeRequest: asynchronousFetchRequest error: & asynchronousFetchRequestError]; if (asynchronousFetchRequestError) NSLog (@ "Kan asynchroon ophaalresultaat niet uitvoeren."); NSLog (@ "% @,% @", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription); ]; 

We beginnen met het maken en configureren van een NSFetchRequest bijvoorbeeld om de asynchrone ophaalopdracht te initialiseren. Het is dit ophaalverzoek dat het asynchrone ophaalverzoek op de achtergrond zal uitvoeren.

// Initialize Fetch Request NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName: @ "TSPItem"]; // Sorteerbeschrijvingen toevoegen [fetchRequest setSortDescriptors: @ [[NSSortDescriptor sortDescriptorWithKey: @ "createdAt" oplopend: YES]]];

Om een ​​te initialiseren NSAsynchronousFetchRequest we roepen bijvoorbeeld aan initWithFetchRequest: completionBlock:, binnenkomen fetchRequest en een voltooiingsblok.

// Asynchrone ophaalopdracht initialiseren NSAsynchronousFetchRequest * asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest: fetchRequest completionBlock: ^ (NSAsynchronousFetchResult * result) dispatch_async (dispatch_get_main_queue (), ^ // Asynchroon ophaalresultaat verwerken [weakSelf processAsynchronousFetchResult: result];) ; ];

Het voltooiingsblok wordt aangeroepen wanneer het asynchrone ophaalverzoek klaar is met het uitvoeren van zijn ophaalverzoek. Het voltooiingsblok neemt één argument van het type NSAsynchronousFetchResult, die het resultaat van de query bevat, evenals een verwijzing naar de oorspronkelijke asynchrone ophaalopdracht.

In het voltooiingsblok roepen we aan processAsynchronousFetchResult:, passeren in de NSAsynchronousFetchResult voorwerp. We zullen deze hulpmethode in enkele ogenblikken bekijken.

Het uitvoeren van de asynchrone ophaalopdracht is bijna identiek aan hoe we een uitvoeren NSBatchUpdateRequest. Wij bellen executeRequest: error: in de context van het beheerde object, doorgeven van de asynchrone ophaalopdracht en een aanwijzer naar een NSError voorwerp.

[self.managedObjectContext performBlock: ^ // Asynchrone ophaalaanvraag uitvoeren NSError * asynchronousFetchRequestError = nil; NSAsynchronousFetchResult * asynchronousFetchResult = (NSAsynchronousFetchResult *) [weakSelf.managedObjectContext executeRequest: asynchronousFetchRequest error: & asynchronousFetchRequestError]; if (asynchronousFetchRequestError) NSLog (@ "Kan asynchroon ophaalresultaat niet uitvoeren."); NSLog (@ "% @,% @", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription); ];

Merk op dat we de asynchrone ophaalopdracht uitvoeren door te bellen performBlock: in de context van het beheerde object. Hoewel dit niet strikt noodzakelijk is sinds de viewDidLoad methode, waarin we het asynchrone ophaalverzoek maken en uitvoeren, wordt aangeroepen op de hoofdthread, het is een goede gewoonte en de beste werkwijze om dit te doen.

Hoewel de asynchrone ophaalopdracht op de achtergrond wordt uitgevoerd, moet u er rekening mee houden dat de executeRequest: error: methode keert onmiddellijk terug, en geeft ons een NSAsynchronousFetchResult voorwerp. Zodra de asynchrone ophaalopdracht is voltooid, is dat hetzelfde NSAsynchronousFetchResult object wordt gevuld met het resultaat van de ophaalopdracht.

Ten slotte controleren we of het asynchrone ophaalverzoek zonder problemen is uitgevoerd door te controleren of het NSError object is gelijk aan nul.

Stap 4: Het asynchrone ophaalresultaat verwerken

De processAsynchronousFetchResult: methode is niets meer dan een hulpmethode waarbij we het resultaat van de asynchrone ophaalopdracht verwerken. We hebben de view controller ingesteld items eigendom met de inhoud van de resultaten eindresultaat eigenschap en laad de tabelweergave opnieuw.

- (void) processAsynchronousFetchResult: (NSAsynchronousFetchResult *) asynchronousFetchResult if (asynchronousFetchResult.finalResult) // Update-items [self setItems: asynchronousFetchResult.finalResult]; // Reload Table View [self.tableView reloadData]; 

Stap 5: Build and Run

Bouw het project en voer de applicatie uit in de iOS Simulator. Het kan u verbazen dat uw toepassing vastloopt wanneer het de asynchrone ophaalopdracht probeert uit te voeren. Gelukkig vertelt de uitvoer in de console wat er mis ging.

*** Beëindigen app vanwege niet-afgevangen uitzondering 'NSInvalidArgumentException', reden: 'NSConfinementConcurrencyType-context  kan asynchrone ophaalopdracht niet ondersteunen  met ophaalopdracht  (entity: TSPItem; predicate: ((null)); sortDescriptors: (("(createdAt, ascending, compare :)")); type: NSManagedObjectResultType;). '

Als u het artikel over Core Data en concurrency niet hebt gelezen, bent u misschien in de war door wat u leest. Onthoud dat Core Data drie typen concurrency declareert, NSConfinementConcurrencyTypeNSPrivateQueueConcurrencyType, en NSMainQueueConcurrencyType. Wanneer u een beheerde objectcontext maakt door de klassen aan te roepen in het methode, het concurrency-type van de resulterende beheerde objectcontext is gelijk aan NSConfinementConcurrencyType. Dit is het standaard concurrency-type.

Het probleem is echter dat asynchroon ophalen niet compatibel is met de NSConfinementConcurrencyType type. Zonder in te gaan op te veel details, is het belangrijk om te weten dat de asynchrone ophaalopdracht de resultaten van de ophaalopdracht moet samenvoegen met de context van het beheerde object die de asynchrone ophaalopdracht heeft uitgevoerd. Het moet weten in welke verzendrij het dit kan doen en daarom alleen NSPrivateQueueConcurrencyType en NSMainQueueConcurrencyType ondersteuning voor asynchroon ophalen. De oplossing is echter heel eenvoudig.

Stap 6: De beheerde objectcontext configureren

Open TSPAppDelegate.m en werk het managedObjectContext methode zoals hieronder getoond.

- (NSManagedObjectContext *) managedObjectContext if (_managedObjectContext) return _managedObjectContext;  NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator]; if (coördinator) _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSMainQueueConcurrencyType]; [_managedObjectContext setPersistentStoreCoordinator: coördinator];  retourneer _managedObjectContext; 

De enige wijziging die we hebben aangebracht is het vervangen van de in het methode met initWithConcurrencyType:, binnenkomen NSMainQueueConcurrencyType als het argument. Dit betekent dat de context van het beheerde object alleen toegankelijk is via de hoofdthread. Dit werkt prima, zolang we de performBlock: of performBlockAndWait: methoden om toegang te krijgen tot de context van het beheerde object.

Voer het project nog een keer uit om er zeker van te zijn dat onze wijziging het probleem inderdaad heeft opgelost.

4. Vooruitgang tonen

De NSAsynchronousFetchRequest klasse voegt ondersteuning toe voor het bewaken van de voortgang van de ophaalopdracht en het is zelfs mogelijk om een ​​asynchrone ophaalopdracht te annuleren, bijvoorbeeld als de gebruiker besluit dat het te lang duurt om te voltooien.

De NSAsynchronousFetchRequest klasse maakt gebruik van de NSProgress klasse voor voortgangsrapportage en annulering van een asynchrone ophaalopdracht. De NSProgress class, beschikbaar sinds iOS 7 en OS X 10.9, is een slimme manier om de voortgang van een taak te bewaken zonder de taak nauw te koppelen aan de gebruikersinterface.

De NSProgress klasse ondersteunt ook annulering, dat is hoe een asynchroon ophaalverzoek kan worden geannuleerd. Laten we uitvinden wat we moeten doen om voortgangsrapportage voor de asynchrone ophaalopdracht te implementeren.

Stap 1: SVProgressHUD toevoegen

We laten de gebruiker de voortgang zien van het asynchrone ophaalverzoek met de SVProgressHUD-bibliotheek van Sam Vermette. Download de bibliotheek van GitHub en voeg de SVProgressHUD map naar uw Xcode-project.

Stap 2: instellen NSProgress 

In dit artikel zullen we de NSProgress klasse in veel detail, maar voel je vrij om er meer over te lezen in de documentatie. We creëren een NSProgress bijvoorbeeld in het blok dat we overhandigen aan de performBlock: methode in de view controller's viewDidLoad methode.

// Maak voortgang NSProgress * progress = [NSProgress progressWithTotalUnitCount: 1]; // Word Huidig ​​[progress becomeCurrentWithPendingUnitCount: 1];

Het zal je misschien verbazen dat we het totale aantal eenheden hebben ingesteld 1. De reden is simpel. Wanneer Core Data de asynchrone ophaalopdracht uitvoert, weet het niet hoeveel records het in de permanente winkel zal vinden. Dit betekent ook dat we de relatieve voortgang voor de gebruiker niet kunnen weergeven, een percentage. In plaats daarvan zullen we de gebruiker de absolute vooruitgang tonen - het aantal records dat hij heeft gevonden.

U kunt dit probleem verhelpen door een ophaalopdracht uit te voeren om het aantal records op te halen voordat u de asynchrone ophaalopdracht uitvoert. Ik doe dit liever niet, omdat dit ook betekent dat het ophalen van de records uit de permanente winkel langer duurt om te voltooien vanwege het extra ophaalverzoek aan het begin.

Stap 3: Een waarnemer toevoegen

Wanneer we de asynchrone ophaalopdracht uitvoeren, krijgen we onmiddellijk een NSAsynchronousFetchResult voorwerp. Dit object heeft een vooruitgang eigendom, dat van het type is NSProgress. Het is dit vooruitgang eigendom dat we moeten observeren als we voortgangsupdates willen ontvangen.

// Asynchrone ophaalopdracht uitvoeren [self.managedObjectContext uitvoerenBlock: ^ // Maak voortgang NSProgress * progress = [NSProgress progressWithTotalUnitCount: 1]; // Word Huidig ​​[progress becomeCurrentWithPendingUnitCount: 1]; // Asynchrone ophaalopdracht uitvoeren NSError * asynchronousFetchRequestError = nil; NSAsynchronousFetchResult * asynchronousFetchResult = (NSAsynchronousFetchResult *) [self.managedObjectContext executeRequest: asynchronousFetchRequest error: & asynchronousFetchRequestError]; if (asynchronousFetchRequestError) NSLog (@ "Kan asynchroon ophaalresultaat niet uitvoeren."); NSLog (@ "% @,% @", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription);  // Observer toevoegen [asynchronousFetchResult.progress addObserver: self forKeyPath: @ "completedUnitCount" opties: NSKeyValueObservingOptionNew context: ProgressContext]; // Ontslag Huidig ​​[progress resignCurrent]; ];

Merk op dat we bellen resignCurrent op de vooruitgang object om het eerdere in balans te brengen becomeCurrentWithPendingUnitCount: noemen. Houd er rekening mee dat beide methoden moeten worden aangeroepen op dezelfde thread.

Stap 4: De waarnemer verwijderen

In het voltooiingsblok van de asynchrone ophaalopdracht verwijderen we de waarnemer en negeren we de voortgang HUD.

// Asynchrone ophaalopdracht initialiseren NSAsynchronousFetchRequest * asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest: fetchRequest completionBlock: ^ (resultaat NSAsynchronousFetchResult *) dispatch_async (dispatch_get_main_queue (), ^ // Verwerping van voortgang HUD [SVProgressHUD negeren]; // Asynchrone ophaalactie verwerken Resultaat [weakSelf processAsynchronousFetchResult: result]; // Observer verwijderen [result.progress removeObserver: weakSelf forKeyPath: @ "completedUnitCount" context: ProgressContext];); ];

Voordat we het implementeren observeValueForKeyPath: ofObject: change: context:, we moeten een import-instructie toevoegen voor de SVProgressHUD-bibliotheek, de statische variabele declareren ProgressContext die we doorgeven als context bij het toevoegen en verwijderen van de waarnemer en de voortgang HUD weergeven voordat het asynchrone ophaalverzoek wordt gemaakt.

#import "SVProgressHUD / SVProgressHUD.h"
static void * ProgressContext = & ProgressContext;
- (void) viewDidLoad [super viewDidLoad]; // Helpers __weak TSPViewController * weakSelf = self; // Show Progress HUD [SVProgressHUD showWithStatus: @ "Ophalen van gegevens" maskType: SVProgressHUDMaskTypeGradient]; // Initialize Fetch Request NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName: @ "TSPItem"]; // Sorteerbeschrijvingen toevoegen [fetchRequest setSortDescriptors: @ [[NSSortDescriptor sortDescriptorWithKey: @ "createdAt" oplopend: YES]]]; // Asynchrone ophaalopdracht initialiseren NSAsynchronousFetchRequest * asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest: fetchRequest completionBlock: ^ (resultaat NSAsynchronousFetchResult *) dispatch_async (dispatch_get_main_queue (), ^ // Verwerping van voortgang HUD [SVProgressHUD negeren]; // Asynchrone ophaalactie verwerken Resultaat [weakSelf processAsynchronousFetchResult: result]; // Observer verwijderen [result.progress removeObserver: weakSelf forKeyPath: @ "completedUnitCount" context: ProgressContext];); ]; // Asynchrone ophaalopdracht uitvoeren [self.managedObjectContext uitvoerenBlock: ^ // Maak voortgang NSProgress * progress = [NSProgress progressWithTotalUnitCount: 1]; // Word Huidig ​​[progress becomeCurrentWithPendingUnitCount: 1]; // Asynchrone ophaalopdracht uitvoeren NSError * asynchronousFetchRequestError = nil; NSAsynchronousFetchResult * asynchronousFetchResult = (NSAsynchronousFetchResult *) [weakSelf.managedObjectContext executeRequest: asynchronousFetchRequest error: & asynchronousFetchRequestError]; if (asynchronousFetchRequestError) NSLog (@ "Kan asynchroon ophaalresultaat niet uitvoeren."); NSLog (@ "% @,% @", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription);  // Observer toevoegen [asynchronousFetchResult.progress addObserver: self forKeyPath: @ "completedUnitCount" opties: NSKeyValueObservingOptionNew context: ProgressContext]; // Ontslag Huidig ​​[progress resignCurrent]; ]; 

Stap 5: voortgangsrapportage

Het enige wat ons nog te doen staat, is het implementeren van observeValueForKeyPath: ofObject: change: context: methode. We controleren of context is gelijk aan ProgressContext, Maak een staat object door het aantal voltooide records uit de verandering woordenboek en werk de voortgang HUD bij. Merk op dat we de gebruikersinterface op de hoofdthread updaten.

- (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) objectwijziging: (NSDictionary *) verander context: (void *) context if (context == ProgressContext) dispatch_async (dispatch_get_main_queue (), ^ // Create Status NSString * status = [NSString stringWithFormat: @ "% li Records opgehaald", (lang) [[wijzig objectForKey: @ "nieuw"] integerValue]]; // Show Progress HUD [SVProgressHUD setStatus: status];); 

5. Dummy-gegevens

Als we onze applicatie goed willen testen, hebben we meer gegevens nodig. Hoewel ik het gebruik van de volgende aanpak in een productieapplicatie niet raad, is het een snelle en eenvoudige manier om de database met gegevens te vullen.

Open TSPAppDelegate.m en werk het toepassing: didFinishLaunchingWithOptions: methode zoals hieronder getoond. De populateDatabase methode is een eenvoudige hulpmethode waarbij we dummy data toevoegen aan de database.

- (BOOL) applicatie: (UIApplication *) applicatie didFinishLaunchingWithOptions: (NSDictionary *) launchOptions // Populate Database [self populateDatabase]; ... return YES; 

De implementatie is eenvoudig. Omdat we alleen dummy-gegevens eenmaal willen invoegen, controleren we de database met gebruikersstandaarden voor de sleutel @ "DidPopulateDatabase". Als de sleutel niet is ingesteld, voegen we dummy-gegevens in.

- (void) populateDatabase // Helpers NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; als ([ud objectForKey: @ "didPopulateDatabase"]) terugkeert; for (NSInteger i = 0; i < 1000000; i++)  // Create Entity NSEntityDescription *entity = [NSEntityDescription entityForName:@"TSPItem" inManagedObjectContext:self.managedObjectContext]; // Initialize Record NSManagedObject *record = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext]; // Populate Record [record setValue:[NSString stringWithFormat:@"Item %li", (long)i] forKey:@"name"]; [record setValue:[NSDate date] forKey:@"createdAt"];  // Save Managed Object Context [self saveManagedObjectContext]; // Update User Defaults [ud setBool:YES forKey:@"didPopulateDatabase"]; 

 Het aantal records is belangrijk. Als u van plan bent om de toepassing op de iOS Simulator uit te voeren, is het goed om 100.000 of 1.000.000 records in te voegen. Dit werkt niet zo goed op een fysiek apparaat en duurt te lang om te voltooien.

In de voor loop, we maken een beheerd object en vullen het met gegevens. Merk op dat we de wijzigingen in de context van het beheerde object niet opslaan tijdens elke iteratie van de voor lus.

Ten slotte werken we de database met gebruikersstandaarden bij om ervoor te zorgen dat de database de volgende keer dat de toepassing wordt gestart niet wordt ingevuld.

Super goed. Start de applicatie in de iOS Simulator om het resultaat te zien. U zult merken dat het even duurt voordat het asynchrone ophaalverzoek begint met het ophalen van records en het bijwerken van de voortgang HUD.

6. Veranderingen doorbreken

Door de opgehaalde resultatencontroller-klasse te vervangen door een asynchroon ophaalverzoek, hebben we een paar stukjes van de toepassing verbroken. Het tikken op het vinkje van een actiepunt lijkt bijvoorbeeld niet langer te werken. Terwijl de database wordt bijgewerkt, geeft de gebruikersinterface de wijziging niet weer. De oplossing is vrij eenvoudig te repareren en ik laat het aan jou over om een ​​oplossing te implementeren. U zou nu voldoende kennis moeten hebben om het probleem te begrijpen en een geschikte oplossing te vinden.

Conclusie

Ik ben er zeker van dat u het ermee eens bent dat asynchroon ophalen verrassend gemakkelijk is. Het zware werk wordt gedaan door Core Data, wat betekent dat het niet nodig is om de resultaten van de asynchrone ophaalopdracht handmatig samen te voegen met de context van het beheerde object. Uw enige taak is om de gebruikersinterface bij te werken wanneer het asynchrone ophaalverzoek u de resultaten oplevert. Samen met batch-updates is het een geweldige aanvulling op het Core Data-raamwerk.

Dit artikel besluit ook deze serie over Core Data. U hebt veel geleerd over het framework voor kerngegevens en u weet alle essentiële zaken om kerngegevens in een echte toepassing te gebruiken. Core Data is een krachtig framework en met de release van iOS 8 heeft Apple ons laten zien dat het elk jaar beter wordt.