Kjernedata og Swift: NSFetchedResultsController

Core Data- og Swift: NSFetchedResultsController
12
Del
4
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 og Swift.Core Data- og Swift. Relasjoner og Mer FetchingCore Data- og Swift: 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.

Forutsetninger

Det jeg dekke i denne serien på kjernedata er aktuelt for iOS 7+ og OS X 10.10+, men fokuset vil være på iOS. I denne serien vil jeg jobbe med Xcode 7.1 og Swift 2.1. Hvis du foretrekker Objective-C, så jeg anbefaler å lese min tidligere serie på grunndata rammeverket.

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
, satt språk til Swift, og sette Enheter
til iPhone
. Fordi jeg har lyst til å vise deg hvordan du oppretter en Core data program fra bunnen av, må du kontrollere at avkrysningsruten Bruk kjernedata er avmerket. Fortell Xcode hvor du vil lagre prosjektet og traff Opprett for å opprette prosjektet.

2. Kjernen data Setup

Åpne AppDelegate.swift Hotell og erklærer tre late lagret egenskaper managedObjectModel av type NSManagedObjectModel, managedObjectContext av type NSManagedObjectContext, og persistentStoreCoordinator av type NSPersistentStoreCoordinator. Hvis du er forvirret av dette trinnet, så anbefaler jeg at du besøker den første artikkelen i denne serien, som dekker kjernedata stabelen i detalj
//MARK: -. //MARK: Kjerne data Stacklazy Var managedObjectModel: NSManagedObjectModel = {} () lat Var managedObjectContext: NSManagedObjectContext = {} () lat Var persistentStoreCoordinator: NSPersistentStoreCoordinator = {} ()

Merk at jeg har også lagt til en import statement for Core data rammen på toppen av AppDelegate .swift
.
import UIKitimport CoreData

Husk at vi bruker lat nøkkelord for å dovent sette opp grunndata stabelen. Dette betyr at vi instantiate klarte objektet kontekst, klarte objektmodellen, og den vedvarende butikken koordinator øyeblikket de trengs av programmet. Følgende gjennomføringen bør se veldig kjent
lat Var managedObjectModel. NSManagedObjectModel = {la modelURL = NSBundle.mainBundle () URLForResource ("Ferdig", withExtension: "momd").! returnere NSManagedObjectModel (contentsOfURL: modelURL)!} () lat Var managedObjectContext: NSManagedObjectContext = {la persistentStoreCoordinator = self.persistentStoreCoordinator //Initial Managed Object Context Var managedObjectContext = NSManagedObjectContext (concurrencyType: .MainQueueConcurrencyType) //Konfigurer Managed Object Context managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator tilbake managedObjectContext} () lat Var persistentStoreCoordinator: NSPersistentStoreCoordinator = {//initial Vedvarende Butikk Koordinator lar persistentStoreCoordinator = NSPersistentStoreCoordinator (managedObjectModel: self.managedObjectModel) //URL Dokumenter Directory la webadresser = NSFileManager.defaultManager () URLsForDirectory (.DocumentDirectory, inDomains. : .UserDomainMask) la applicationDocumentsDirectory = URLer [(URLs.count - 1)] //URL Vedvarende Butikk la URLPersistentStore = applicationDocumentsDirectory.URLByAppendingPathComponent ("Done.sqlite") gjør {//Legg Vedvarende Store til Vedvarende Butikk koordinator prøve persistentStoreCoordinator.addPersistentStoreWithType (NSSQLiteStoreType, konfigurasjon: null, URL: URLPersistentStore, alternativer: nil)} catch {//Befolke Error Var Userinfo = [String: AnyObject] () Userinfo [NSLocalizedDescriptionKey] = "Det oppstod en feil å opprette eller laste lagrede data programmets. " Userinfo [NSLocalizedFailureReasonErrorKey] = "Det oppstod en feil å opprette eller laste lagrede data programmets." Userinfo [NSUnderlyingErrorKey] = feil som NSError la wrappedError = NSError (domene: "com.tutsplus.Done", kode: 1001, Userinfo: Userinfo) NSLog ("Uløste error \\ (wrappedError), \\ (wrappedError.userInfo)") abort ()} 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 Vare
. 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 objektkontekst innlegg 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 Anmeldelser 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 var innsatt
, 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
valgfri offentlig func controllerWillChangeContent (controller: NSFetchedResultsController). Valgfri offentlig func controllerDidChangeContent (controller: NSFetchedResultsController) valgfri offentlig func kontrolleren (controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType Type: NSFetchedResultsChangeType) valgfri offentlig func kontrolleren (controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath ?, forChangeType Type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath) valgfri offentlig func kontrolleren (controller: NSFetchedResultsController, sectionIndexTitleForSectionName section: String) - > String?

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 ViewController klasse, og koble den i dreieboken. . Ikke glem å gjøre ViewController klasse i samsvar med UITableViewDataSource og UITableViewDelegate protokoller
importere UIKitclass ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {IBOutlet svak Var Tableview: UITableView! styre func viewDidLoad () {super.viewDidLoad ()}}

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, ToDoCell, 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 ToDoCell 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 ViewController underklasse og kall den AddToDoViewController. Åpne AddToDoViewController.swift, erklærer en stikkontakt tekstfeltet av type UITextField og tilpasse visningen kontrolleren til UITextFieldDelegate protokollen
importere UIKitclass AddToDoViewController. UIViewController, UITextFieldDelegate {IBOutlet svak Var Textfield: UITextField! styre func viewDidLoad () {super.viewDidLoad ()}}

Før vi legge til visningen kontrolleren til dreieboken, legge til følgende to handlingene til visningen kontrolleren implementering fil
//MARK: -. //MARK: handlinger @ IBAction func avbryte (avsender: AnyObject) {}IBAction func redning (avsender: AnyObject) {}

Åpne dreieboken en gang til og legge til en bar knapp element med en identifikator for Legg
til høyre for navigasjonslinjen i ViewController. Legg til en ny visning kontrolleren til dreieboken og sette sin klasse AddToDoViewController 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 (_ :) handling til venstre bar knappen element og lagre (_ :) handling til høyre bar knappen element.

Legg til en UITextField objekt til visningen kontrolleren syn og posisjon det 20 poeng under navigasjonslinjen. Tekstfeltet skal ligge på 20 poeng under navigasjonslinjen. Merk at oppsettet begrensningen på de beste referanser toppen layout guide
.

Koble tekstfeltet med tilsvarende uttak i visningen kontrolleren og sette visningen kontrolleren som tekstfeltet delegat. Endelig kontrollere dra fra baren knappen element av ViewController til navigasjonskontrolleren hvorav AddToDoViewController er roten view controller. Sett segue typen til Presenter modally Hotell og setter naturlig overgang identifikator til SegueAddToDoViewController 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 ViewController 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
//MARK: -. //MARK: Tabell Data Source Methodsfunc Tableview (Tableview: UITableView, numberOfRowsInSection seksjon: Int) - > Int {return 0}

For å tilfreds kompilatoren, trenger vi også å gjennomføre Tableview (_: cellForRowAtIndexPath :). På toppen av AddToDoViewController.swift, legge til en konstant for cellen gjenbruk identifikator
importere UIKitclass ViewController. UIViewController, UITableViewDataSource, UITableViewDelegate {la ReuseIdentifierToDoCell = "ToDoCell" ...}

Implementering Tableview (_: cellForRowAtIndexPath: ) er ganske enkel siden vi ikke gjør noe spesielt med tabellvisningen celle ennå func Tableview (Tableview: UITableView, cellForRowAtIndexPath indexPath. NSIndexPath) - > UITableViewCell {la celle = tableView.dequeueReusableCellWithIdentifier (ReuseIdentifierToDoCell, forIndexPath: indexPath) som! ToDoCell returnere celle}
Trinn 3: Lagre og Avbryt

Åpne AddToDoViewController klasse og implementere avbryte (_ :) og lagre (_ :) metoder som vist nedenfor. Vi vil oppdatere sine implementeringer senere i denne opplæringen
//MARK: -. //MARK: Handlinger @ IBAction func avbryte (avsender: AnyObject) {dismissViewControllerAnimated (sant, ferdigstillelse: null)} @ IBAction func spare (avsender: AnyObject) {dismissViewControllerAnimated (sant, ferdigstillelse: null)}

Bygg og kjøre programmet i simulatoren 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 AddToDoViewController og fjerne den ved å enten trykke avbryte eller lagre knappen.

6. Legge til 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 ViewController 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 overskriften fil av ViewController klassen. Merk at vi også legger til en import statement for Core data rammeverket på toppen
importere UIKitimport CoreDataclass ViewController. UIViewController, UITableViewDataSource, UITableViewDelegate {la ReuseIdentifierToDoCell = "ToDoCell"IBOutlet svak Var Tableview: UITableView! Var managedObjectContext: NSManagedObjectContext! ...}

Åpne Main.storyboard
velger dreieboken sin første visningen kontrolleren, en UINavigationController eksempel, og sette Storyboard ID
å StoryboardIDRootNavigationController i Identity Inspector < . .no>

I søknaden delegat søknad (_: didFinishLaunchingWithOptions :) metoden, får vi en referanse til ViewController eksempel roten visning kontrolleren av navigeringskontrollen, og sette managedObjectContext eiendom. Den oppdaterte programmet (_: didFinishLaunchingWithOptions :) metode ser ut som følger:
func program (applikasjon: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]) - >? Bool {//Fetch Hoved Storyboard la mainStoryboard = UIStoryboard (navn: "Main", bunt: null) //instantiate Root Navigation Controller la rootNavigationController = mainStoryboard.instantiateViewControllerWithIdentifier ("StoryboardIDRootNavigationController") som! UINavigationController //Konfigurer View Controller la viewController = rootNavigationController.topViewController som? ViewController hvis la viewController = viewController {viewController.managedObjectContext = self.managedObjectContext} //Konfigurer Window vinduet? .rootViewController = RootNavigationController return true}

For å være sikker på at alt fungerer, legge til følgende utskrifts uttalelse til viewDidLoad () metoden av ViewController klassen
styre func viewDidLoad () {super.viewDidLoad () print (managedObjectContext)}
Trinn 2:. Initial den NSFetchedResultsController Instance

Åpne gjennomføringen fil av ViewController klasse og erklære en lat lagret egenskap av typen NSFetchedResultsController. Navn eiendommen fetchedResultsController. En NSFetchedResultsController eksempel har også en delegat eiendom som trenger å samsvare med NSFetchedResultsControllerDelegate protokollen. Fordi ViewController eksempel vil tjene som delegat på NSFetchedResultsController eksempel, må vi tilpasse den ViewController klasse til NSFetchedResultsControllerDelegate protokollen som vist nedenfor
importere UIKitimport CoreDataclass ViewController. UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {la ReuseIdentifierToDoCell = "ToDoCell "IBOutlet svak Var Tableview: UITableView! Var managedObjectContext: NSManagedObjectContext! Var fetchedResultsController: NSFetchedResultsController = {} () ...}

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 kontrollerens viewDidLoad () -metoden, initial vi hente forespørsel ved å sende "Item" til initWithEntityName (_ :) metoden. 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
lat Var fetchedResultsController. NSFetchedResultsController = {//initial Fetch Request la fetchRequest = NSFetchRequest (entitetsnavn: "Item") //Legg Sorter Descriptors la sortDescriptor = NSSortDescriptor (key: "createdAt", stigende: true) fetchRequest.sortDescriptors = [sortDescriptor] //Initial Hentet Resultater Controller la fetchedResultsController = NSFetchedResultsController (fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: null, cacheName: null) //Konfigurer Hentet Resultater Controller fetchedResultsController.delegate = selv tilbake fetchedResultsController} ()

initialisering av hentede resultater kontrolleren er ganske grei. Init (fetchRequest: managedObjectContext: sectionNameKeyPath: cacheName :) metoden tar fire argumenter:

for hente forespørsel

den klarte objektet sammenheng hentet resultater kontrolleren vil følge
< li> en del 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 () i viewDidLoad (). Merk at dette er en kaste metode, som betyr at vi trenger å pakke det inn i en do-fangst uttalelse. Den performFetch () metoden er lik den executeFetchRequest (_ :) metoden i NSManagedObjectContext klassen.
Styre func viewDidLoad () {super.viewDidLoad () gjør {prøve self.fetchedResultsController.performFetch ()} catch {la fetchError = feil som NSError print ("\\ (fetchError), \\ (fetchError.userInfo)")}}
Trinn 3: Implementering
Representant Protocol

Med hentet resultater kontrolleren satt opp og klar til bruk, vi behov for å implementere NSFetchedResultsControllerDelegate protokollen. Som vi så tidligere, definerer protokollen fem metoder, hvorav tre er av interesse for oss i denne opplæringen:

controllerWillChangeContent (Controller: NSFetchedResultsController)

controllerDidChangeContent (controller: NSFetchedResultsController)

controller (controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath ?, forChangeType Type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)

Den første to 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 mulig at flere endringer inntreffer samtidig. I stedet for å oppdatere brukergrensesnitt for hver endring, vi batch oppdaterer brukergrensesnittet når alle endringer er gjort

I vårt eksempel, koker dette ned til følgende implementeringer av controllerWillChangeContent. (Controller: NSFetchedResultsController) og controllerDidChangeContent ( . controller: NSFetchedResultsController)
//MARK: - //MARK: Hentet Resultater Controller Deleger Methodsfunc controllerWillChangeContent (controller: NSFetchedResultsController) {tableView.beginUpdates ()} funk controllerDidChangeContent (controller: NSFetchedResultsController) {tableView.endUpdates ()} < p> Gjennomføringen av kontrolleren (controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath ?, forChangeType Type: NSFetchedResultsChangeType, newIndexPath:? NSIndexPath) 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 det data strukturen endres. Det er opp til oss å visualisere disse endringene i, for eksempel, en tabellvisning

Gjennomføringen av kontrolleren (controller. NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath ?, forChangeType Type: NSFetchedResultsChangeType, newIndexPath: ? NSIndexPath) ser skremmende, men la meg gå gjennom det
func kontrolleren (controller. NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath ?, forChangeType Type: NSFetchedResultsChangeType, newIndexPath:? NSIndexPath) {switch (type) {case .Insert: hvis la indexPath = newIndexPath {tableView.insertRowsAtIndexPaths ([indexPath], withRowAnimation: .Fade)} break; tilfellet .Delete: hvis la indexPath = indexPath {tableView.deleteRowsAtIndexPaths ([indexPath], withRowAnimation: .Fade)} break; tilfellet .Update: hvis la indexPath = indexPath {la celle = tableView.cellForRowAtIndexPath (indexPath) som! ToDoCell configureCell (celle, atIndexPath: indexPath)} break; tilfellet .Kjør: hvis la indexPath = indexPath {tableView.deleteRowsAtIndexPaths ([indexPath], withRowAnimation: .Fade)} if la newIndexPath = newIndexPath {tableView.insertRowsAtIndexPaths ([newIndexPath], withRowAnimation: .Fade)} break; }}

Endringen typen er av typen NSFetchedResultsChangeType. Denne oppregning har fire medlems verdier:

Sett

Slett

Flytt

Oppdater

Navnene er ganske selvforklarende. Hvis typen er Insert, vi forteller utsikten bordet for å sette inn en rad på newIndexPath. Tilsvarende, hvis typen Slett, fjerner vi raden på indexPath fra visningen tabellen

Hvis en post er oppdatert, oppdaterer vi den tilsvarende rad i tabellvisningen ved å påberope configureCell (_:. AtIndexPath :), en hjelper metode som godtar en ToDoCell objekt og en NSIndexPath objekt. Vi vil implementere denne metoden i et øyeblikk.

Hvis endringen typen er lik Flytt, fjerner vi rad på indexPath og sette inn en rad på newIndexPath å reflektere posten oppdaterte posisjon i hentede 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 :.

Selv om tabellvisning i vår prøveprogrammet vil bare ha én del, la oss be hentet resultater kontrolleren for antall seksjoner Vi gjøre 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 og egenskaper, inkludert numberOfObjects. Dette gir oss det vi trenger for å gjennomføre de to første metodene for UITableViewDataSource protokollen
func numberOfSectionsInTableView (Tableview: UITableView) - > Int {if la seksjoner = fetchedResultsController.sections {return sections.count} return 0} func Tableview (Tableview. UITableView, numberOfRowsInSection seksjon: Int) - > Int {if la seksjoner = fetchedResultsController.sections {la sectionInfo = seksjoner [seksjonen] retur sectionInfo.numberOfObjects} retur 0}

Neste opp er Tableview (_: cellForRowAtIndexPath :) og configureCell (_ : atIndexPath :). 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 ReuseIdentifierToDoCell og passerer cellen og indeksen banen til configureCell (_: atIndexPath :)
func Tableview (Tableview: UITableView, cellForRowAtIndexPath indexPath. NSIndexPath) - > UITableViewCell {la celle = tableView.dequeueReusableCellWithIdentifier (ReuseIdentifierToDoCell, forIndexPath: indexPath) som! ToDoCell //Konfigurer Tabell Cell configureCell (celle, atIndexPath: indexPath) avkastning 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.