Core Data- og Swift: subclassing NSManagedObject 
 17 
 Del 
 3 
 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 og Swift.Core Data- og Swift. MigrationsCore Data- og Swift: Samtidighet 
 1. Innledning 
 
 Tidligere i denne serien, skapte vi gjort, et enkelt program for å lære mer om NSFetchedResultsController klassen. I dette prosjektet har vi brukt nøkkelverdien koding (KVC) og nøkkelverdi observere (KVO) å opprette og oppdatere poster. Dette fungerer fint, men fra det øyeblikket prosjektet har noen form for kompleksitet, vil du raskt får problemer. Ikke bare er KVC syntaks ordrik, valueForKey (_ :) og SetValue (_: Forkey :), kan det også introdusere feil som er et resultat av skrivefeil. Følgende kodebit illustrerer dette problemet godt 
 record.setValue (NSDate (), Forkey: "createdat"). Record.setValue (NSDate (), Forkey: "CreatedAt") record.setValue (NSDate (), Forkey: "createdAt") record.setValue (NSDate (), Forkey: "CREATEDAT") 
 Hver uttalelse i ovennevnte kodebiten returnerer et annet resultat. Faktisk vil enhver uttalelse resultere i et unntak bortsett fra tredje setningen, som bruker riktig nøkkel som angitt i datamodellen. 
 
 Ovennevnte problem er lett løses ved å bruke string konstanter, men det er ikke poenget Jeg prøver å gjøre. Nøkkelverdi koding er flott, men det er ordrik og vanskelig å lese hvis du er vant til Swifts dot syntaks. For å gjøre arbeidet med NSManagedObject tilfeller lettere, er det bedre å lage en NSManagedObject underklasse for hver enhet av datamodellen og det er hva du vil lære i denne artikkelen. 
 
 2. Subclassing NSManagedObject 
 
 For å spare litt tid, vi kommer til å besøke Ferdig, programmet vi laget tidligere i denne serien. Last den ned fra GitHub og åpne den i Xcode. 
 
 Opprette en NSManagedObject underklasse er veldig enkelt. Selv om det er mulig å lage en NSManagedObject underklasse manuelt for en enhet, er det lettere å la Xcode gjøre jobben for deg. 
 
 Åpne datamodell av prosjektet,  Done.xcdatamodeld 
, og velg  Vare 
 enhet. Velg  New > Fil ... 
 fra Xcode  Fil 
 menyen velger du  NSManagedObject underklasse 
 mal fra  kjernedata 
 delen, og klikk  Neste Anmeldelser . 
 
 Merk av i boksen av riktig datamodellen,  Ferdig 
, fra listen over datamodeller og klikk  Neste 
. 
 
 I neste trinn , blir du bedt om å velge de enhetene som du ønsker å opprette en NSManagedObject underklasse. Merk av i boksen for  Vare 
 enhet og klikk  Neste 
. 
 
 Velg et sted å lagre klassen filene i NSManagedObject underklasse og sørg for at  Bruk skalar eiendommer for primitive datatyper 
 er avmerket. Når du arbeider med Objective-C, er dette alternativet en viktig faktor. Men for Swift, er det best å sjekke det som det gjør koden mer lesbar og mindre komplekse. Ikke glem å sette språk til Swift og klikk  Opprett 
 å opprette NSManagedObject underklasse for  Vare 
 enhet. 
 
 3. NSManagedObject Anatomy 
 
 Naviger til filer Xcode opprettet for deg og ta en titt på innholdet. Xcode skal ha opprette to filer for deg: 
 
 Item.swift 
 
 Element + CoreDataProperties.swift 
 
 Hvis du bruker en tidligere versjon av Xcode, deretter Xcode kan ha skapt bare én fil. Jeg anbefaler å bruke Xcode 7-helst Xcode 7.1 eller høyere for å følge med. Innholdet i Item.swift bør være ganske lett å forstå. 
 ////Item.swift //Ferdig ////Laget av Bart Jacobs på 24/10/15 .//Copyright © 2 015 Envato Tuts +. Alle rettigheter reservert .//import Foundationimport CoreDataclass Sak: NSManagedObject {//Sett inn koden her for å legge til funksjonalitet til din klarte objekt underklasse} 
 Som du kan se, har Xcode opprettet en klasse for oss, Element, som arver fra NSManagedObject. Kommentaren Xcode har lagt til klassen gjennomføringen er viktig. Hvis du ønsker å legge til funksjonalitet til klassen, bør du legge den til her. La oss nå ta en titt på innholdet i Element + CoreDataProperties.swift. 
 ////Element + CoreDataProperties.swift //Ferdig ////Laget av Bart Jacobs på 24/10/15 .//Copyright © 2 015 Envato Tuts +. Alle rettigheter reservert .////Velg "Opprett NSManagedObject Subclass ..." fra Core data redaktør menyen //slette og gjenskape denne implementeringen filen for den oppdaterte modellen .//import Foundationimport CoreDataextension Element {NSManaged Var createdAt: NSTimeIntervalNSManaged Var gjort: BoolNSManaged Var navn: String} 
 Det finnes en rekke viktige detaljer og noen nye konsepter. Det første man legger merke til er at denne filen definerer en forlengelse på Element klassen. Utvidelsen erklærer tre egenskaper som samsvarer med attributtene til Element enhet, som vi definerte i datamodellen. DenNSManaged attributtet er lik dendynamic attributtet i Objective-C. DenNSManaged attributtet forteller kompilatoren at lagring og gjennomføringen av disse eiendommene vil bli gitt under kjøring. Selv om dette kan høres flott, Apples dokumentasjon sier klart atNSManaged bør bare brukes i sammenheng med grunndata. 
 
 Hvis dette høres litt forvirrende, så husk atNSManaged er nødvendig for kjernedata for å gjøre sitt arbeid ogNSManaged attributtet skal kun brukes til NSManagedObject klasser. 
 
 Hva skjer hvis du endrer en enhet og generere filene for foretakets NSManagedObject underklasse igjen? Det er et godt spørsmål, og Xcode advarer deg om dette scenariet. På toppen av Element + CoreDataProperties.swift, under opphavsrett, har Xcode lagt til en kommentar for avklaring. 
 //Velg "Opprett NSManagedObject Subclass ..." fra Core data redaktør menyen //slette og gjenskape denne implementeringen fil for den oppdaterte modellen. 
 Når du genererer filene for en enhet, Xcode vil bare erstatte filer av filtypen. Med andre ord, hvis du legger til et attributt til Element enhet og generere filene for NSManagedObject underklasse, Xcode erstatter Element + CoreDataProperties.swift, forlater Item.swift urørt. Det er derfor Xcode ber deg om å legge til funksjonalitet i Item.swift. Dette er veldig viktig å huske på. 
 
 De typer eiendommer kan være litt overraskende. Navnet Eiendommen er av typen NSString ?, fordi attributtet er merket som valgfritt i datamodellen. Den createdAt Eiendommen er av typen NSTimeInterval, fordi vi sjekket avkrysnings Bruk skalare eiendommer for primitive datatyper. Det samme gjelder for den gjort eiendom, som er av typen Bool. 
 
 Hvis vi ikke hadde sjekket av i boksen, ville createdAt eiendom være av typen NSDate? og gjort eiendommen ville være av typen NSNumber ?. Mens det kan være enklere å bruke NSDate tilfeller er det sikkert mindre praktisk å jobbe med NSNumber gjenstander hvis alt du ønsker er å få og satt boolske verdier. 
 
 4. Oppdatere Prosjekt 
 
 Med Element klassen klar til bruk, er det på tide å oppdatere prosjektet ved å erstatte eventuelle forekomster av valueForKey (_ :) og SetValue (_:. Forkey :) 
 
 ViewController 
 
 Åpne gjennomføringen fil av ViewController klassen, navigere til configureCell (_: atIndexPath :), og oppdatere gjennomføringen som vist nedenfor 
 func configureCell (celle. ToDoCell, atIndexPath indexPath: NSIndexPath) {//Fetch Record la record = fetchedResultsController.objectAtIndexPath (indexPath) som! Sak //Update Cell hvis la name = record.name {cell.nameLabel.text = navn} cell.doneButton.selected = record.done cell.didTapButtonHandler = {record.done =! Record.done}} 
 Vi har gjort fire endringer. Vi først endret type posten variabel til Element. Den objectAtIndexPath (_ :) metoden i NSFetchedResultsController klassen returnerer en AnyObject eksempel. Men fordi vi vet hentet resultater kontrolleren returnerer et element eksempel vi tvinge nedbrutte resultatet bruker som! operatør. 
 
 Vi erstatter også valueForKey (_ :) samtaler. I stedet bruker vi egenskapene til posten objekt, navn og gjort. Takket være Swifts dot syntaks, er veldig leselig resultatet 
 
 For å oppdatere posten, vi ikke lenger kalle SetValue (_:. Forkey :). I stedet bruker vi prikken syntaksen til å sette rekord gjøres eiendom. Jeg er sikker på at du enig i at dette er mye mer elegant enn å bruke rett tast verdi koding. Vi trenger heller ikke valgfritt bindende for gjort eiendommen siden gjort Eiendommen er av typen Bool. 
 
 Husk at KVC og KVO forbli en integrert del av kjernedata. Kjernen data bruker valueForKey (_ :) og SetValue (_:. Forkey :) under panseret for å få jobben gjort 
 
 AddToDoViewController 
 
 Vi må også gjøre noen endringer i AddToDoViewController klassen . I spare (_ :) metoden, må vi først å oppdatere initialisering av NSManagedObject eksempel. I stedet for initialisering en NSManagedObject eksempel, skaper vi en Varen eksempel 
 //Opprett Entitylet enhet = NSEntityDescription.entityForName ("Item", inManagedObjectContext: self.managedObjectContext). //Initial Recordlet record = Element (enhet: enhet !, insertIntoManagedObjectContext : self.managedObjectContext) 
 For å fylle opp, bruker vi prikken syntaksen i stedet for SetValue (_:. Forkey :) metode som vist nedenfor 
 //Befolke Recordrecord.name = namerecord.createdAt = NSDate () .timeIntervalSince1970 
 UpdateToDoViewController 
 
 Den siste klassen vi trenger å oppdatere er UpdateToDoViewController klasse. La oss begynne med å endre type posten eiendommen til punkt !. 
 import UIKitimport CoreDataclass UpdateToDoViewController: UIViewController {IBOutlet svak Var Textfield: UITextField! Var rekord: Element! Var managedObjectContext: NSManagedObjectContext! ...} 
 Denne endringen vil resultere i en advarsel i ViewController klassen. Å se hva som er galt, åpen ViewController.swift og naviger til prepareForSegue (_:. Avsender :) metode 
 
 Vi ber hentet resultater kontrolleren for posten på den valgte indeksen banen. Typen posten variabelen er NSManagedObject, men UpdateToDoViewController klassen forventer et element eksempel. Løsningen er svært enkel som du kan se nedenfor. 
 Hvis la indexPath = tableView.indexPathForSelectedRow {//Fetch Record la record = fetchedResultsController.objectAtIndexPath (indexPath) som! Sak //Konfigurer View Controller viewController.record = record viewController.managedObjectContext = managedObjectContext} 
 Leder tilbake til UpdateToDoViewController klassen og oppdatere viewDidLoad () -metoden som vist nedenfor. 
 Styre func viewDidLoad () {super.viewDidLoad ( ) hvis la name = record.name {textField.text = navn}} 
 Vi trenger også å oppdatere lagre (_ :) metoden, som erstatter vi SetValue (_:. Forkey :) med prikken syntaks 
 //Update Recordrecord.name = navn 
 Bygg prosjektet og kjøre programmet i simulatoren for å se om alt er fortsatt fungerer som forventet. 
 
 5. Relasjoner 
 
 Den nåværende datamodellen inneholder ingen relasjoner, men la oss legge til noen for å se hvordan en NSManagedObject underklasse med relasjoner ser ut. Som vi har sett i den forrige artikkelen i denne serien, må vi først å lage en ny versjon av datamodellen. Velg datamodellen i  Prosjekt Navigator Hotell og velg  Legg Model versjon ... 
 fra  Editor 
 menyen. Sette  Version navn 
 til  Ferdig 2 Hotell og basere modellen på dagens datamodell,  Ferdig 
. Klikk  Fullfør 
 å opprette den nye datamodellen versjon. 
 
 Åpne  Ferdig 2.xcdatamodel 
, opprette en ny enhet som heter  Brukeranmeldelser, og legge til en attributt  navn 
 av type  String 
. Legg et forhold  elementer Hotell og satt målet til  Vare 
. La den inverse forholdet tomt for nå. Med  elementer 
 forholdet valgt, åpner du  Data Model Inspektør 
 på høyre og sette forholdet typen til  Slik Mange 
. En bruker kan ha mer enn ett element knyttet til dem. 
 
 Velg  Element 
 enhet, skape et forhold  bruker 
, og angi dette som reisemål til  User 
. Sett inverse forholdet til  elementer 
. Dette vil automatisk sette den inverse forholdet mellom de  elementer 
 forholdet til  Brukeranmeldelser enhet. Merk at brukerforhold er ikke valgfritt. 
 
 Før skaper vi NSManagedObject underklasser for begge enhetene, må vi fortelle datamodell som datamodell versjon den skal bruke. Velg  Done.xcdatamodeld 
, åpne  File Inspektør 
 på høyre side, og sette dagens modell versjon til  Ferdig 2 
. Når du gjør dette, dobbeltsjekke at du har valgt  Done.xcdatamodeld 
, ikke  Done.xcdatamodel 
 
 Velg  New >.; Fil ... 
 fra  Fil 
 menyen og velg  NSManagedObject underklasse 
 mal fra  Kjerne data 
 delen. Fra listen over datamodeller, velg  Ferdig 2 
. 
 
 Velg begge enhetene fra listen over enheter. Fordi vi har endret  Element 
 enhet, trenger vi å regenerere forlengelse for den tilsvarende NSManagedObject underklasse. 
 
 Vare 
 
 La oss først ta en titt på endringer av nygenererte Sak klasse. Som du kan se nedenfor, utvidelse på Element klasse (Sak + CoreDataProperties.swift) inneholder ett ekstra eiendom, bruker av type Bruker ?. 
 import Foundationimport CoreDataextension Element {NSManaged Var createdAt: NSTimeIntervalNSManaged Var gjort: Bool NSManaged Var navn: String? NSManaged Var bruker:? Bruker} 
 Dette er hva en  Til En 
 forhold ser ut i en NSManagedObject underklasse. Xcode er smart nok til å antyde at den type brukeren eiendommen er User ?, den NSManagedObject underklasse vi skapt et øyeblikk siden. Selv om brukerforhold er merket som ikke valgfritt i datamodellen, er den type brukeren eiendommen User ?. Det er ikke klart om dette er tilsiktet eller en feil i Xcode. 
 
 Gjennomføringen av Element klasse (Item.swift) er ikke oppdatert med Xcode. Husk at Xcode ikke berører denne filen hvis det allerede eksisterer. 
 
 Brukeranmeldelser 
 Med det vi har lært så langt, er lett å forstå bruksklassen. Ta en titt på forlengelse av User klasse (User + CoreDataProperties.swift). Det første du vil legge merke til er at den type elementer eiendommen er NSSet ?. Dette bør ikke være en overraskelse, fordi vi allerede visste at kjernedata bruker settene forekomster av NSSet klasse, for lagring av medlemmene i en  til mange 
  
 forholdet. Fordi forholdet er merket som valgfritt i datamodellen, typen er NSSet ?. 
 import Foundationimport CoreDataextension User {NSManaged Var navn: String? NSManaged Var elementer:? NSSet} 
 Det er hvor lett det er å jobbe med relasjoner i NSManagedObject klasser 
 
 6.. Migrations 
 
 Hvis du bygger prosjektet og kjøre programmet i simulatoren, vil du legge merke til at programmet krasjer. Utgangen i Xcode konsoll forteller at datamodellen brukes til å åpne den vedvarende butikken er ikke kompatibel med den som ble brukt til å opprette det. Grunnen til dette problem er forklart i detalj i den tidligere artikkelen i denne serien. Hvis du ønsker å lære mer om vandringer og hvordan du trygt endre datamodellen, så foreslår jeg at du leser den artikkelen. 
 
 Konklusjon 
 
 subclassing NSManagedObject er veldig vanlig når man jobber med kjernedata. Ikke bare legge den typen sikkerhet, også gjør det å jobbe med relasjoner mye enklere. 
 
I neste utgaven av denne serien tar vi en nærmere titt på kjernedata og samtidighet. Samtidighet er et vanskelig begrep i nesten alle programmeringsspråk, men vet hvilke fallgruver å unngå, gjør det mye mindre skummelt.

