Core Data- og Swift: Mer NSFetchedResultsController
15
Del
to
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 som heter kjernedata og Swift.Core Data- og Swift. NSFetchedResultsControllerCore Data- og Swift: 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.
Forutsetninger
Det jeg dekke i denne serien på kjernedata er aktuelt til 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. Oppdatere en Record navn
Trinn 1: Lag View Controller
Start med å lage en ny UIViewController underklasse heter UpdateToDoViewController. I UpdateToDoViewController.swift
, 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
importere UIKitimport CoreDataclass UpdateToDoViewController. UIViewController {IBOutlet svak Var Textfield: UITextField! Var rekord: NSManagedObject! Var managedObjectContext: NSManagedObjectContext! ...}
Deretter oppretter to handlingene, kansellere (_ :) og lagre (_ :). Sine implementeringer kan forbli tom for tiden
//MARK: -. //MARK: Handlinger @ IBAction func avbryte (send: AnyObject) {}IBAction func redning (send: AnyObject) {}
Trinn 2 : Oppdatering Storyboard
Åpne hovedstoryboard, Main.storyboard
, legge til en ny visning controller objekt, og sette sin klasse UpdateToDoViewController i Identity Inspector
. Trykk Kontroll og dra fra prototypen celle i ViewController forekomsten til UpdateToDoViewController eksempel. Velg Selection Segue > Vis fra menyen som vises, og, i attributter Inspector
, setter naturlig overgang identifikator til SegueUpdateToDoViewController.
Legg til en UITextField objekt til visningen av UpdateToDoViewController objektet og konfigurere det akkurat som vi gjorde med tekstfeltet i AddToDoViewController klassen. Ikke glem å koble visningen kontrollerens stikkontakt med tekstfeltet.
Som i AddToDoViewController 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 ViewController klassen. La oss begynne med å oppdatere prepareForSegue (_: avsender :), vi hente posten som korresponderer med brukerens valg og gi det til UpdateToDoViewController eksempel
//MARK: -. //MARK: Forbered Segueoverride func prepareForSegue (naturlig overgang: UIStoryboardSegue, avsender:? AnyObject) {if segue.identifier == "SegueAddToDoViewController" {if la navigationController = segue.destinationViewController som? UINavigationController {if la viewController = navigationController.topViewController som? AddToDoViewController {viewController.managedObjectContext = managedObjectContext}}} else if segue.identifier == "SegueUpdateToDoViewController" {if la viewController = segue.destinationViewController som? UpdateToDoViewController {if la indexPath = tableView.indexPathForSelectedRow {//Fetch Record la record = fetchedResultsController.objectAtIndexPath (indexPath) som! NSManagedObject //Konfigurer View Controller viewController.record = record viewController.managedObjectContext = managedObjectContext}}}}
Til slutt, vi implementere Tableview (_: didSelectRowAtIndexPath :) metoden i UITableViewDelegate protokollen. I denne metoden, fjerner du merket vi raden brukeren tappet
//MARK: -. //MARK: Tabell delegat Methodsfunc Tableview (Tableview: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {tableView.deselectRowAtIndexPath (indexPath, animert: true) }
Trinn 4: Fylle tekstfeltet
I viewDidLoad () metoden i UpdateToDoViewController klassen, fylle ut tekstfelt med navnet på den posten som vist nedenfor
//MARK:. - //MARK: Vis Livet Cycleoverride func viewDidLoad () {super.viewDidLoad () hvis la name = record.valueForKey ("navn") som? String {textField.text = navn}}
Trinn 5:. Oppdatere Record
I avbryte (_ :) action, pop vi oppdateringen view controller fra navigasjonskontrolleren navigasjon stack
@ IBAction func avbryte (send: AnyObject) {? navigationController .popViewControllerAnimated (true)}
I spare (_ :) action, vi først sjekke om tekstfeltet er tomt, og viser et varsel hvis det er. Hvis tekstfeltet inneholder en gyldig verdi, oppdaterer vi rekord navn attributt og pop utsikten kontrolleren fra navigasjonskontrolleren navigasjon stack
IBAction func spare (avsender: AnyObject). {La name = textField.text hvis la gjelder tom bil = nevne .isEmpty der gjelder tom bil == false {//Update Record record.setValue (navn, Forkey: "navn")??? do {//Lagre post prøv record.managedObjectContext .Lagre () //Avvis View Controller navigationController .popViewControllerAnimated (true)} catch {la saveError = feil som NSError print ("\\ (saveError), \\ (saveError.userInfo)") //Show Alert Vis showAlertWithTitle ("Warning", meldingen: "Din gjøremål kunne ikke lagres . ", cancelButtonTitle:" OK ")}} else {//Show Alert Vis showAlertWithTitle (" Warning ", meldingen:" Din gjøremål trenger et navn ", cancelButtonTitle:". OK ")}}
Gjennomføringen av showAlertWithTitle (_: melding: cancelButtonTitle :) er identisk med den AddToDoViewController klassen
//MARK: -. //MARK: Helper Methodsprivate func showAlertWithTitle (tittel: String, message: String, cancelButtonTitle: String) {//Initial Alert Controller la alertController = UIAlertController (tittel: tittel, melding: melding, preferredStyle: .Alert) //Konfigurer Alert Controller alertController.addAction (UIAlertAction (tittel: cancelButtonTitle, stil: .DEFAULT, handler: null)) //Present Alert Controller presentViewController (alertController, animert: true, ferdigstillelse: null)}
Dette er alt som trengs for å oppdatere en post ved hjelp av kjernedata. Kjøre programmet for å kontrollere at alt fungerer. Den hentet resultater kontrolleren oppdager automatisk endringen og varsler sin representant, ViewController eksempel. Den ViewController objekt, på sin side, oppdaterer tabellen sikte på å gjenspeile endringen. Så enkelt er det.
2. Oppdatere en Record State
Trinn 1: Oppdatere ToDoCell
Når en bruker kraner på knappen på høyre side av en ToDoCell, må varens tilstand å endre. For å oppnå dette, må vi først å oppdatere ToDoCell klassen. Åpne ToDoCell.swift Hotell og legge en typealias for et behandlingsprogram som heter ToDoCellDidTapButtonHandler. Deretter erklærer en eiendom, didTapButtonHandler, av type ToDoCellDidTapButtonHandler ?.
import UIKittypealias ToDoCellDidTapButtonHandler = () - > () klasse ToDoCell: UITableViewCell {IBOutlet svak Var nameLabel: UILabel! IBOutlet Svak Var doneButton: UIButton! Var didTapButtonHandler: ToDoCellDidTapButtonHandler? ...}
I klassens awakeFromNib () -metoden, påberope vi en hjelper metode, setupView (), for å sette opp tabellvisningen celle
//MARK: -. //MARK: Initializationoverride func awakeFromNib () { super.awakeFromNib () 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 til didTapButton (_ :) hvor påberope vi didTapButtonHandler nedleggelse. 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
//MARK: -. //MARK: Vis Methodsprivate func setupView () {la imageNormal = UIImage (kalt: "button-gjort- normal ") la imageSelected = UIImage (kalt:" button-gjort-valgte ") doneButton.setImage (imageNormal, forState: .Normal) doneButton.setImage (imageNormal, forState: .Disabled) doneButton.setImage (imageSelected, forState: .Selected ) doneButton.setImage (imageSelected, forState: .Highlighted) doneButton.addTarget (selv, handling: "didTapButton:", forControlEvents: .TouchUpInside)} //MARK: - //MARK: Actionsfunc didTapButton (avsender: AnyObject) {if utleid behandleren = didTapButtonHandler {handler ()}}
Trinn 2: Oppdatere ViewController
Takk til NSFetchedResultsController klassen og grunnlaget vi har lagt, vi trenger bare å oppdatere configureCell (_: atIndexPath :) metode i ViewController klassen
func configureCell. (celle: ToDoCell, atIndexPath indexPath: NSIndexPath) {//Fetch Record la record = fetchedResultsController.objectAtIndexPath (indexPath) //Update Cell hvis la name = record.valueForKey ("navn") som? String {cell.nameLabel.text = navn} hvis la gjort = record.valueForKey ("ferdig") som? Bool {cell.doneButton.selected = done} cell.didTapButtonHandler = {if la gjort = record.valueForKey ("ferdig") som? Bool {record.setValue (gjort, Forkey: "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 AppDelegate.swift Hotell og implementere applicationDidEnterBackground (_ :) som vist nedenfor
func applicationDidEnterBackground (søknad. UIApplication) {do {prøve self.managedObjectContext.save ()} catch {la saveError = feil som NSError print ("\\ (saveError), \\ (saveError.userInfo)")}}
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 protokollen som varsler programmets delegat når programmet er i ferd med å bli avsluttet
func applicationWillTerminate (søknad. UIApplication) {do {prøve self.managedObjectContext.save ()} fangsten {la saveError = feil som NSError print ("\\ (saveError), \\ (saveError.userInfo)")}}
Merk at vi har duplisert kode i applicationDidEnterBackground (_ :) og applicationWillTerminate (_ :). La oss være smart og lage en hjelper metode for å lagre klarte objektet sammenheng og kaller dette helper metoden i både delegat metoder
//MARK: -. //MARK: Helper Methodsprivate func saveManagedObjectContext () {do {prøve self.managedObjectContext. Lagre ()} catch {la saveError = feil som NSError print ("\\ (saveError), \\ (saveError.userInfo)")}}
3. Slette Records
Du vil bli overrasket over hvor få linjer det tar å slette poster som bruker NSFetchedResultsController klassen. . Start med å implementere Tableview (_: canEditRowAtIndexPath :) metoden i UITableViewDataSource protokollen
func Tableview (Tableview: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) - > Bool {return true}
Den andre metoden for UITableViewDataSource protokollen som vi trenger for å implementere er Tableview (_: commitEditingStyle: forRowAtIndexPath :). I denne metoden, vi hente klarte objekt brukeren har valgt for sletting, og gi det til deleteObject (_ :) metode av forvaltet objekt sammenheng med den hentet resultater kontrolleren
func Tableview (Tableview:. UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {if (editingStyle == .Delete) {//Fetch Record la record = fetchedResultsController.objectAtIndexPath (indexPath) som! NSManagedObject //Slett Record managedObjectContext.deleteObject (rekord)}}
Fordi vi allerede har implementert NSFetchedResultsControllerDelegate protokollen, brukergrensesnittet oppdateres automatisk, inkludert animasjoner.
Konklusjon
I 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.