Building en handleliste Application From Scratch: Part 2
Del
Del
7
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 Lær iOS SDK Development Fra Scratch.Building en handleliste Application From Scratch:. Part 1Where To Go Neste
I forrige minske, la vi grunnlaget for handleliste søknaden. I første del av denne leksjonen, vil vi begrense anvendelsen av slik at brukeren kan redigere og slette elementer fra listen. I den andre delen av denne leksjonen vi legge muligheten til å velge elementer fra listen for å lage handleliste.
Outline
Som jeg nevnte i forrige artikkel, en av kjernefunksjonene i handleliste søknaden er å administrere en liste over elementer. Vi har gjort en god jobb så langt, men brukeren skal ha muligheten til å redigere og slette elementer fra listen, som vil være i fokus i den første delen av denne opplæringen. I den andre delen, vil vi implementere den andre kjernen funksjon i handleliste søknad, lage en handleliste ved å velge elementer fra listen over elementer.
9. Slette Elementer
Slette elementer fra listen er et viktig tilskudd i form av brukeropplevelsen og generell brukervennlighet. Legge denne evnen innebærer:
fjerne elementet fra visningen kontrollerens elementer eiendom
oppdatere visningen tabellen
lagre endringene til disk
La oss se hvordan dette fungerer i praksis.
Vi må først legge til en redigeringsknapp til navigasjonslinjen. . I visningen kontrolleren viewDidLoad metode, opprette en forekomst av UIBarButtonItem og tilordne den til rightBarButtonItem eiendom visningen kontrollerens navigationItem eiendom
Som i forrige leksjon, skaper vi en bar knapp element ved å ringe initWithBarButtonSystemItem: target : action: initialisering metoden. Den første parameteren som vi passerer er UIBarButtonSystemItemEdit. I tillegg, passerer vi selv som målet og satt handlingen til editItems :. Anmeldelser - (void) viewDidLoad {[super viewDidLoad]; //NSLog (@ "Poster >% @", self.items); //Register klasse for Cell Gjenbruk [self.tableView Register: [UITableViewCell klasse] forCellReuseIdentifier: CellIdentifier]; //Lag Legg Button self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemAdd mål: selv handling:selector (AddItem :)]; //Lag Edit Button self.navigationItem.rightBarButtonItem = [[UIBarButtonItem Alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemEdit mål: selv handling:selector (editItems:)];}
Gjennomføring av editItems: handlingen er bare en linje med kode som du kan se nedenfor. Når brukeren kraner redigeringsknappen, utsikten bordet slås inn i eller ut av redigeringsmodus. Vi gjør dette ved hjelp av et lite triks. Vi ber tabellvisningen om det for tiden er i redigeringsmodus, som returnerer en BOOL verdi, og inverse den returnerte verdien (YES blir NO og vice versa). Metoden vi kaller på tabellvisningen er setEditing: animerte :, som er en spesialisert setter som aksepterer en animasjon parameter Anmeldelser - (åpne) editItems:.! (Id) avsender {[self.tableView setEditing: [self.tableView isEditing] animert. YES];}
Hvis du kjører handleliste programmet i iOS Simulator og trykker på redigeringsknappen, bør du se utsikten bord blir slås inn og ut av redigeringsmodus
To Fremgangsmåtene ifølge fore UITableViewDataSource protokollen er viktige for å muliggjøre redigering i en tabell view:
tableView:canEditRowAtIndexPath:
tableView:commitEditingStyle:forRowAtIndexPath:
When brukeren kraner redigeringsknappen, spør tabellvisningen sin datakilde som rader kan redigeres ved å sende datakilden et budskap om Tableview: canEditRowAtIndexPath :. Når YES er returnert for en bestemt indeks banen, instruerer utsikten tabellen tabellvisningen celle i den tilsvarende raden at det er behov for å veksle inn i eller ut av redigeringsmodus, avhengig av tabellvisning redigeringsmodus.
I praksis betyr dette at tabellvisningen cellen viser eller skjuler sine redigeringskontroller. Dette konseptet er best forstå ved å implementere Tableview: canEditRowAtIndexPath: metode som vist nedenfor Anmeldelser - (BOOL) Tableview:. (UITableView *) Tableview canEditRowAtIndexPath: (NSIndexPath *) indexPath {if ([indexPath rad] == 1) { tilbake NO; } Returnere YES;}
Listen gjennomføring av Tableview: canEditRowAtIndexPath: gjør det mulig å redigere hver rad i tabellen visning med unntak av andre rad. Kjør programmet i iOS Simulator og gi det et forsøk
For handleliste søknaden, må brukeren være i stand til å redigere hver rad i tabellvisningen, noe som betyr at Tableview. CanEditRowAtIndexPath: Bør alltid tilbake JA som vist nedenfor
- (BOOL) Tableview: (UITableView *) Tableview canEditRowAtIndexPath:. (NSIndexPath *) indexPath {return JA;}
Du har kanskje lagt merke til at ingenting skjer når du prøver å slette en rad i tabellvisningen. Puslespillet er ikke ferdig ennå. Når brukeren kraner sletteknappen på rad, sender tabellvisningen sin datakilde et budskap om Tableview: commitEditingStyle: forRowAtIndexPath :. Det andre argumentet for den tilsvarende metode betegner hva slags handlinger brukeren har utført, sette inn eller slette en rad. . Handleliste applikasjonen vil bare gi støtte for å slette rader fra tabellvisningen
Slette rader fra en tabell syn innebærer:
slette det tilsvarende elementet fra visningen kontrollerens elementer eiendom
oppdatere tabellvisningen ved å slette den tilsvarende raden
La oss undersøke gjennomføringen av Tableview: commitEditingStyle: forRowAtIndexPath :. Metoden starter med å sjekke om redigering stilen er lik UITableViewCellEditingStyleDelete som vi bare vil tillate brukeren å slette rader fra tabellvisningen.
Hvis redigerings stilen er lik UITableViewCellEditingStyleDelete, da det tilsvarende elementet er fjernet fra elementer array, er den tilsvarende raden slettet fra visningen bordet, og den oppdaterte listen over elementer er lagret på disken Anmeldelser - (void) Tableview:. (UITableView *) Tableview commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {//Slett objekt fra Items [self.items removeObjectAtIndex: [indexPath ro]]; //Update Tabell [Tableview deleteRowsAtIndexPaths: @ [indexPath] withRowAnimation: UITableViewRowAnimationRight]; //Lagre endringer for å Disk [selvtillit saveItems]; }}
Kjør programmet i iOS Simulator for å teste slette funksjonalitet. Ikke glem å avslutte og relansere programmet for å kontrollere at elementene blir permanent slettet fra listen.
10. Redigere elementer
Vi kunne gjenbruke TSPAddItemViewController klassen for redigering av elementer, men gjenbruk utsikt controller klasse for både tilsette og redigering av elementer kan ofte overcomplicate gjennomføringen så mye at jeg som regel ende opp med å skape en egen UIViewController underklasse for redigering av elementer . Dette vil i første omgang føre til en viss overlapping i forhold til implementering og brukergrensesnitt, men det vil gi oss mer fleksibilitet nedover veien.
Opprette Redigering View Controller
Opprett en ny UIViewController underklasse og navn det TSPEditItemViewController. Header filer av TSPAddItemViewController og TSPEditItemViewController klasser er svært lik
#import < UIKit /UIKit.h >class TSPItem;protocol TSPEditItemViewControllerDelegate;interface TSPEditItemViewController. UIViewController @ eiendom IBOutlet UITextField * nameTextField;property IBOutlet UITextField * priceTextField;property TSPItem * element;property (svak) id < TSPEditItemViewControllerDelegate > delegat; @ enden @ protokollen TSPEditItemViewControllerDelegate < NSObject > - (void) controller: (TSPEditItemViewController *) controller didUpdateItem: (TSPItem *) element;end
Etter import overskriftene av UIKit rammeverk, en fremtids klasse og protokoll erklæring tilsettes. Grensesnittet av klassen er lik som den TSPAddItemViewController klassen. Den viktigste forskjellen er erklæringen av en egenskap for å lagre elementet som blir redigert.
header filen slutter med erklæringen av TSPEditItemViewControllerDelegate protokollen. Protokollen Erklæringen inneholder en metode som kalles når et element er oppdatert. Metoden tar utsikten kontrolleren og den oppdaterte elementet som sine argumenter.
Åpne hovedstoryboard, dra en UIViewController eksempel fra Object Library
, setter sin klasse TSPEditItemViewController, og opprette en manuell trykk
naturlig overgang fra listevisning kontrolleren til redigerings element visning kontrolleren, og kalte den EditItemViewController.
Drag to UITextField forekomstene fra objektbiblioteket til visningen kontrolleren syn og plassere dem som vist på figuren nedenfor. Velg den øverste tekstfeltet, åpner attributter Inspector, og skriv navn i Placeholder feltet. Velg den nederste tekstfeltet, og i attributter Inspector, setter sin eksempelteksten til Pris og sette tastaturet til Number Pad. Velg visningen kontrolleren objekt, åpner Connections Inspector, og koble nameTextField og priceTextField uttak til tilsvarende tekstfeltet i brukergrensesnittet.
I visningen kontrolleren viewDidLoad metode, opprette lagre knappen som vi gjorde i TSPAddItemViewController klasse Anmeldelser - (void) viewDidLoad {[super viewDidLoad].; //Opprett Lagre Button self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemSave mål: selv handling:selector (lagre:)];}
Gjennomføringen av lagre: handlingen er svært lik den vi implementert i TSPAddItemViewController klassen. Men det er noen små forskjeller som jeg ønsker å påpeke Anmeldelser - (void) sparer:. (Id) avsender {NSString * name = [self.nameTextField tekst]; float pris = [[self.priceTextField tekst] floatValue]; //Update element [self.item setName: navn]; [self.item setPrice: prisen]; //Varsle Delegat [self.delegate controller: selv didUpdateItem: self.item]; //Pop View Controller [self.navigationController popViewControllerAnimated: YES];}
I stedet for å sende navnet og pris verdier til representanten, vi direkte oppdatering av elementet og passerer den oppdaterte elementet til visningen kontrollerens delegat. Fordi utsikten kontrolleren er et barn utsikt kontrollør av en navigasjonskontrolleren, vi avviser visningen kontrolleren ved spratt det av navigasjons stabelen.
Viser redigere element View Controller
I en noen minutter, vil vi implementere funksjonalitet som gjør det mulig for brukeren å velge elementer fra listevisning kontrolleren for å legge dem til i handleliste. Brukeren vil kunne gjøre dette ved å trykke på en rad i listevisning. Spørsmålet melder seg da hvordan brukeren vil kunne redigere et element hvis peke på rad er reservert for å legge til et element i handleliste?
UIKit rammeverket gir en detaljert avsløring knappen for akkurat dette use case. En detalj avsløring knappen er en liten, blå chevron plassert på høyre side av et bord visning celle. For å legge til en detalj avsløring knapp til en tabellvisning celle, må vi revidere Tableview: cellForRowAtIndexPath: metoden i listevisning kontrolleren og endre det som vist nedenfor Anmeldelser - (UITableViewCell *) Tableview:. (UITableView *) Tableview cellForRowAtIndexPath : (NSIndexPath *) indexPath {//dequeue Gjenbruk Cell UITableViewCell * celle = [Tableview dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath: indexPath]; //Hente varen TSPItem * element = [self.items objectAtIndex: [indexPath ro]]; //Konfigurer Cell [cell.textLabel setText: [elementnavn]]; [celle setAccessoryType: UITableViewCellAccessoryDetailDisclosureButton]; returnere celle;}
Hver tabell visning celle har en accessoryType eiendom. I gjennomføringen nedenfor, setter vi det til UITableViewCellAccessoryDetailDisclosureButton. Som du kanskje har lagt merke til, har ingeniørene hos Apple ikke liker korte navn.
Hvordan tabellvisningen varsle representanten når detaljene avsløring knappen tappes? Ikke overraskende, definerer UITableViewDelegate protokollen den Tableview: accessoryButtonTappedForRowWithIndexPath: metode for dette formålet. Ta en titt på gjennomføringen Anmeldelser - (void) Tableview: (UITableView *) Tableview accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *) indexPath {//Hente varen TSPItem * element = [self.items objectAtIndex: [indexPath ro]].; if (element) {//Oppdater merket [selv setSelection: element]; //Utfør Segue [selv performSegueWithIdentifier: @ "EditItemViewController" avsender bolig:]; }}
Vi henter riktig element fra elementer eiendom og lagre den i utvalget, en privat eiendom på listevisning kontrolleren som vi vil erklære på et øyeblikk. Vi deretter utføre naturlig overgang med identifikator EditItemViewController
Før vi oppdaterer gjennomføringen av prepareForSegue:.. Avsender :, må vi erklære en privat eiendom for å lagre det valgte elementet
#import "TSPListViewController.h" # import "TSPItem.h"@interface TSPListViewController ()property NSMutableArray * elementer;property TSPItem * valg;end
Vi trenger også å importere header fil av TSPEditItemViewController klassen i TSPListViewController.h Anmeldelser og tilpasse den TSPListViewController klasse til TSPEditItemViewControllerDelegate protokollen
#import < UIKit /UIKit.h > #import "TSPAddItemViewController.h" #import "TSPEditItemViewController.h"@interface TSPListViewController. UITableViewController < TSPAddItemViewControllerDelegate, TSPEditItemViewControllerDelegate >end
Den oppdaterte gjennomføring av prepareForSegue: avsender: er ganske enkelt som du kan se nedenfor. Vi får en henvisning til redigerings elementet visning controller og satt sine delegere og elementegenskaper
- (void) prepareForSegue:. (UIStoryboardSegue *) segue avsender: (id) avsender {if ([segue.identifier isEqualToString: @ "AddItemViewController"]) {//Destinasjon View Controller UINavigationController * nc = (UINavigationController *) segue.destinationViewController; //Fetch Legg til element View Controller TSPAddItemViewController * vc = [nc.viewControllers firstObject]; //Set Delegat [vc setDelegate bolig:]; } Else if ([segue.identifier isEqualToString: @ "EditItemViewController"]) {//Fetch Rediger element View Controller TSPEditItemViewController * vc = (TSPEditItemViewController *) segue.destinationViewController; //Set Delegat [vc setDelegate bolig:]; [vc setItem: self.selection]; }}
Gjennomføringen av TSPEditItemViewController klassen er nesten fullført. I sin viewDidLoad metoden vi fylle ut tekstfelt med data fra elementet eiendommen. Fordi setText: metode for et tekstfelt bare godtar en NSString eksempel, må vi bryte den flyte verdien av varens pris eiendom i en snor for å vise den i priceTextField
- (void) viewDidLoad {[super. viewDidLoad]; //Opprett Lagre Button self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemSave mål: selv handling:selector (spare :)]; //Fylle tekstfelt hvis (self.item) {[self.nameTextField setText: [self.item name]]; [self.priceTextField setText: [NSString stringWithFormat: @ "% f", [self.item prisen]]]; }}
Vedta
Representant Protocol
Vedta TSPEditItemViewControllerDelegate protokollen er begrenset til gjennomføring av kontroller: didUpdateItem: metode som vist nedenfor. Det kan overraske deg at vi ikke oppdaterer datakilden av utsikten tabellen. Alt vi gjør i representantens metoden er reload én rad med tabellvisningen Anmeldelser - (void) controller: (TSPEditItemViewController *) controller didUpdateItem:. (TSPItem *) item {//Hente varen for (int i = 0; i < [self.items telle]; i ++) {TSPItem * anItem = [self.items objectAtIndex: i]; if ([[anItem UUID] isEqualToString: [elementet UUID]]) {//Update Tabell Row NSIndexPath * indexPath = [NSIndexPath indexPathForRow: i inSection: 0]; [self.tableView reloadRowsAtIndexPaths: @ [indexPath] withRowAnimation: UITableViewRowAnimationFade]; }} //Lagre elementer [selvtillit saveItems];}
Grunnen til at vi ikke trenger å oppdatere tabellvisningen datakilde, den varer array, er at den oppdaterte elementet ble vedtatt med referanse til redigerings element view controller . Med andre ord, det objektet som redigeringselementvisningen controller oppdatert er det samme objektet som finnes i elementer array. Dette er en av de fine fordelene med å arbeide med objekter og pekere.
Ikke glem å lagre listen over elementer for å sørge for at endringer er skrevet til disk. Kjør programmet for å teste redigering funksjonalitet.
11. Opprette Shopping List View Controller
Før vi utforske datakilden av handlelistevisning controller, la oss lage noen stillas å jobbe med. Opprett en ny UITableViewController underklasse og name it TSPShoppingListViewController
Åpne gjennomføringen fil av den nye klassen og legge til to private eiendommer av typen NSArray til klassen forlengelse.
elementer, som vil inneholder en komplett liste over elementer
Shopping, som bare vil inneholde elementer av handlelisten
Siden vi skal overstyre de setter-metoder for begge eiendommene, må vi erklære egenskaper som nonatomic. Ikke bekymre deg om den nøyaktige betydningen av dette for nå
#import < UIKit /UIKit.h >interface TSPShoppingListViewController. UITableViewController @ eiendom (nonatomic) NSArray * elementer;property (nonatomic) NSArray * Shopping;end
Ideen er å laste liste over elementer hver gang en endring er gjort i listen, og deretter analysere liste over elementer og trekke ut bare de elementene som har sitt inShoppingList eiendom satt til YES. Disse elementene vil bli lagt til handleliste array.
Et annet alternativ vil være å lagre handleliste i en egen fil, men ulempen med denne tilnærmingen vil være at vi må holde elementene i listevisning controller og varer i handleliste synkronisert. Dette er å be om trøbbel hvis du spør meg.
Custom settere
De setter-metoder elementer og Shopping vil gjøre det meste av tunge løft for oss. Ta en titt på gjennomføringen av setItems :. Når _items instansvariabelen oppdateres (satt med en ny verdi), er buildShoppingList metode som kalles på visningen controller Anmeldelser - (åpne) setItems:. (NSArray *) elementer {if (! _items = Stk) {_items = elementer; //Bygg handleliste [selvtillit buildShoppingList]; }}
La oss se hva den buildShoppingList metoden ser ut Anmeldelser - (void) buildShoppingList {NSMutableArray * buffer = [[NSMutableArray Alloc] init].; for (int i = 0; i < [self.items telle]; i ++) {TSPItem * element = [self.items objectAtIndex: i]; if ([element inShoppingList]) {//Legg til element til buffer [buffer addObject: element]; }} //Sett handleliste self.shoppingList = [NSArray arrayWithArray: buffer];}
buildShoppingList metoden fyller den Shopping matrise med elementer som har sitt inShoppingList eiendom satt til YES. I buildShoppingList metoden, skaper vi en foranderlig rekke å midlertidig lagre handlelisteelementer. Vi iterere gjennom listen av elementer og legge hvert element til foranderlig matrise som har en inShoppingList eiendom YES. Til slutt satt vi Shopping eiendommen med innholdet i foranderlig array.
Ikke glem å importere tekstfilen av TSPItem klassen på toppen.
#import "TSPItem.h "
Vi styre også setShoppingList setter for å laste utsikten bordet hver gang Shopping matrisen endres eller oppdateres Anmeldelser - (void) setShoppingList:. (NSArray *) Shopping {if (! _shoppingList = Shopping) {_shoppingList = handleliste; //Reload Tabell [self.tableView reloadData]; }}
Vise handleliste
Implementere metodene i UITableViewDataSource protokollen skal være en lek nå. Ta en titt på gjennomføringen av hver metode under Anmeldelser - (NSInteger) numberOfSectionsInTableView: (UITableView *) Tableview {return 1;} - (NSInteger) Tableview:. (UITableView *) Tableview numberOfRowsInSection: (NSInteger) seksjon {return [ ,,,0],self.shoppingList count];} - (UITableViewCell *) Tableview: (UITableView *) Tableview cellForRowAtIndexPath: (NSIndexPath *) indexPath {//dequeue Gjenbruk Cell UITableViewCell * celle = [Tableview dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath: indexPath]; //Hente varen TSPItem * element = [self.shoppingList objectAtIndex: [indexPath ro]]; //Konfigurer Cell [cell.textLabel setText: [elementnavn]]; returnere celle;}
Ikke glem å erklære cellen gjenbruk identifikator og registrere UITableViewCell klassen som vi har gjort i TSPListViewController klassen
implementation TSPShoppingListViewControllerstatic NSString * CellIdentifier = @ "Cell Identifier"; -. ( void) viewDidLoad {[super viewDidLoad]; //Register klasse for Cell Gjenbruk [self.tableView Register: [UITableViewCell klasse] forCellReuseIdentifier: CellIdentifier];}
Laste elementer
Som jeg forklarte tidligere, viktig fordel med å bruke listen over elementer for å lagre og bygge handleliste er at programmet lagrer hvert element i bare ett sted. Dette gjør oppdatere elementer i listen, og i handleliste mye mindre av en hodepine. Den loadItems metoden er identisk med den vi implementert i TSPListViewController klassen Anmeldelser - (åpne) loadItems {NSString * filepath = [selv pathForItems].; if ([[NSFileManagers defaultManager] fileExistsAtPath: filepath]) {//self.items = [NSMutableArray arrayWithContentsOfFile: filepath]; self.items = [NSKeyedUnarchiver unarchiveObjectWithFile: filepath]; } Else {self.items = [NSMutableArray matrise]; }}
Selvfølgelig er det pathForItems metode identisk også, ettersom vi legger listen over elementer fra samme fil som i TSPListViewController klassen Anmeldelser -. (NSString *) pathForItems {NSArray * stier = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask, YES); NSString * dokumenter = [stier lastObject]; tilbake [dokumenter stringByAppendingPathComponent: @ "items.plist"];}
Når du finner deg selv å duplisere kode, bør du høre en alarmklokke ringing. Duplisere kode er ikke problematisk mens du implementere en ny funksjon. Etterpå, derimot, bør du vurdere å ommøblerer koden din for å minimere mengden dobbeltarbeid i programmets kodebasen. Dette er et svært viktig begrep i utvikling av programvare, og er ofte referert til som TØRR, Ikke gjenta deg selv. . Chris Peters skrev en stor artikkel om Tuts + ca TØRR programmering
Før vi satte TSPShoppingListViewController klassen til å bruke, må vi oppdatere klassens initWithCoder: metode. I tillegg til å sette tittelen på visningen kontrolleren, vi også laste liste over elementer som automatisk fyller den Shopping matrisen som vi så tidligere Anmeldelser - (id) initWithCoder:. (NSCoder *) aDecoder {selv = [super initWithCoder : aDecoder]; if (egen-) {//Set Tittel self.title = @ "handleliste"; //Laste Elementer [selvtillit loadItems]; } Returnere selv;}
Det siste trinnet er å initialisere handlelistevisning kontrolleren ved å oppdatere den viktigste storyboard. Dette innebærer å legge en UITableViewController eksempel innstillinger sin klasse TSPShoppingListViewController, bygge det i en navigeringskontroller, og skape en relasjon naturlig overgang mellom fanelinjen kontrolleren og navigeringskontrolleren. Navngi segue ShoppingListViewController. Velg tabellen visning av handlelistevisning kontrolleren og angi antall prototype celler til 0.
Kjør programmet for å se om alt fungerer som det skal. Selvfølgelig er det handleliste tom og vi har ikke en måte å legge til elementer i handleliste. La oss rette på dette i neste trinn.
11. Legge til elementer i handleliste
Som jeg skrev tidligere, er ideen å legge til et element i handleliste når den er tappet i listevisning kontrolleren. For å forbedre brukeropplevelsen, hvis en vare er til stede i handleliste, viser vi en grønn hake til venstre for elementet navn. Hvis et element som allerede er i handleliste tappes, så det er fjernet fra handleliste og grønt merke forsvinner. Dette betyr at vi trenger å ta en titt på Tableview: didSelectRowAtIndexPath: metoden i UITableViewDelegate protokollen
Før vi implementere Tableview. DidSelectRowAtIndexPath :, laste ned kildefilene for denne leksjonen. I mappen som heter Resources, finne filer med navnet checkmark.png og [email protected], og legge begge disse filene til prosjektet. Vi trenger dem i en liten stund
I den første linjen i Tableview. DidSelectRowAtIndexPath :, vi sende tabellen vise en melding av deselectRowAtIndexPath: animerte: å oppheve rad brukeren avlyttet. Når en rad tappes, bør det bare bli markert for en umiddelbar derav denne tillegg. Neste, vi hente det tilsvarende elementet for den valgte raden og oppdatere inShoppingList eiendom varen (YES blir NO og vice versa) Anmeldelser - (void) Tableview:. (UITableView *) Tableview didSelectRowAtIndexPath: (NSIndexPath *) indexPath { [Tableview deselectRowAtIndexPath: indexPath animerte: YES]; //Hente varen TSPItem * element = [self.items objectAtIndex: [indexPath ro]]; //Update Element [element setInShoppingList: [element inShoppingList]]; //Update Cell UITableViewCell * celle = [Tableview cellForRowAtIndexPath: indexPath]; if ([element inShoppingList]) {[cell.imageView setImage: [UIImage imageNamed: @ "hake"]]; } Else {[cell.imageView setImage: null]; } //Lagre elementer [selvtillit saveItems];}
Basert på verdien av varen er setInShoppingList eiendom, vi enten vise eller skjule den grønne haken. Vi viser den haken ved å sette bildet tilhører tabellvisningen cellens bildeVis eiendom. Hver UITableViewCell eksempel inneholder en bildevisning på sin venstre (en forekomst av UIImageView klasse). Ved å sette bildevisningen image eiendom til null, er bildevisningen blank, og viser ingen bilde
Gjennomføringen av Tableview. DidSelectRowAtIndexPath: endene ved å spare en liste over elementer til disken for å forsikre deg om at endringene er permanente .
Hvordan handleliste vite når et element i listevisning kontrolleren er tappet av brukeren? Handlelistevisning controller vil ikke oppdatere sin tabellvisning automatisk hvis en endring ble gjort til en liste over elementer i listevisning kontrolleren. I tillegg ønsker vi ikke listevisning kontrolleren og handlelistevisning kontrolleren til å kommunisere direkte med hverandre for å hindre enhver form for tett kopling.
En løsning på dette problemet er bruken av varslinger. Når listevisning kontrolleren gjør en endring i listen over elementer, det legger ut en melding med et bestemt navn til varslingssenter, et objekt som forvalter varslinger. Objekter som er interessert i visse varslinger kan legge seg som observatører av disse varslene, noe som betyr at de kan reagere når de varsler er lagt ut til melding sentrum.
Hvordan gjør alt dette arbeidet? Det er tre trinn:
handlelistevisning controller starter med å fortelle varslingssenteret at det er interessert i å motta meldinger med et navn på TSPShoppingListDidChangeNotification
Listen View Controller innlegg en varsling til varslingssenteret når den oppdaterer listen over elementer
når handlelistevisning kontrolleren mottar meldingen fra varslingssenteret, oppdaterer den datakilden og tabellvisning svar
Før vi gjennomføre de tre trinnene jeg nettopp har beskrevet, er det en god idé å ta en nærmere titt på NSNotificationCenter klassen.
I et nøtteskall, forvalter NSNotificationCenter kringkasting av meldinger. Objekter i en applikasjon kan registrere seg med et varsel sentrum for å motta varslinger hjelp addObserver: velgeren: navn: objekt: hvor
første argumentet
er objektet som skal motta varslinger ( observatøren)
velger
er handlingen som skal utløses når observatøren mottar meldingen
navn
er navnet på varsling
siste argument
er objektet som sender meldingen
Hvis det siste argumentet er satt til null, mottar observatør hver varsler med det angitte navnet.
Motta Påminnelser
revidere initWithCoder: metoden i TSPShoppingListViewController klassen og legge til visningen kontrolleren eksempel som observatør for å motta varslinger med et navn TSPShoppingListDidChangeNotification Anmeldelser - (id. ) initWithCoder: (NSCoder *) aDecoder {selv = [super initWithCoder: aDecoder]; if (egen-) {//Set Tittel self.title = @ "handleliste"; //Legg Observer [[NSNotificationCenter defaultCenter] addObserver bolig: Velger:selector (updateShoppingList :) navn: @ "TSPShoppingListDidChangeNotification" objekt: null]; } Returnere selv;}
Handlingen utløses når visningen kontrolleren mottar en melding med det navnet er updateShoppingList :. Vi setter objektet til null som det spiller egentlig ingen rolle hvilket objekt som sendte meldingen.
Før vi implementere updateShoppingList :, trenger vi å endre viewDidLoad metoden i handlelistevisning kontrolleren. I viewDidLoad, legger vi elementer fra disk Anmeldelser - (void) viewDidLoad {[super viewDidLoad].; //Laste Elementer [selvtillit loadItems]; //Register klasse for Cell Gjenbruk [self.tableView Register: [UITableViewCell klasse] forCellReuseIdentifier: CellIdentifier];}
Svare på varslings
Metoden som utløses når observatøren mottar en melding har et bestemt format som du kan se nedenfor. Det aksepterer ett argument, er at varslings objekt som er av typen NSNotification. Varslings objekt holder en referanse til objektet som postet meldingen, og det kan også inneholde en ordliste med tilleggsinformasjon. Gjennomføringen av updateShoppingList: Metoden er ganske enkel, det vil si den loadItems metoden kalles på visningen kontrolleren, noe som betyr at en liste over elementer lastes inn fra disk. Resten skjer automatisk takket være tilpassede setter-metoder som vi gjennomførte tidligere Anmeldelser - (void) updateShoppingList:. (NSNotification *) varslings {//Laste Objekt [selvtillit loadItems];}
Sendings Påminnelser
Den tredje brikken i puslespillet er å legge ut et varsel når listen over elementer er endret av listevisning kontrolleren. Vi kan gjøre dette i saveItems metoden i TSPListViewController klasse Anmeldelser - (åpne) saveItems {NSString * filepath = [selv pathForItems].; [NSKeyedArchiver archiveRootObject: self.items toFile: filepath];