Arbeide med NSURLSession Del 3

I de foregående opplæringsprogrammene har vi utforsket grunnleggende for NSURLSession API. Det er en annen funksjon av NSURLSession API som vi ikke har sett på ennå, det vil si opplasting og nedlastinger utenom prosessen. I de neste to opplæringsprogrammene vil jeg vise deg hvordan du lager en veldig enkel podcastklient som muliggjør bakgrunnsnedlastinger.


Introduksjon

Podcast-klienten som vi skal skape, vil egentlig ikke være så funksjonell. Det vil tillate brukeren å spørre iTunes Search API for en liste over podcaster, velge en podcast og laste ned episoder. Siden vi fokuserer på NSURLSession API, vil vi ikke gå inn i å spille episodene programmet lastes ned.

Prosjektet vil imidlertid lære deg hvordan du bruker dataoppgaver og laster ned oppgaver i en ekte verdensapplikasjon. Podcast-klienten vil også aktivere bakgrunnsnedlastinger som vi vil utnytte NSURLSession's ut-av-prosess API. Vi har ganske mange ting å gjøre, så la oss ikke kaste bort tid og komme i gang.


1. Prosjektoppsett

Slå opp Xcode 5, velg Nytt> Prosjekt ... fra Fil menyen, og velg Enkeltvisningsprogram mal fra listen over iOS-applikasjonsmaler. Navn søknaden Singlecast, sett Enhetsfamilie til iPhone, og fortell Xcode hvor du vil lagre prosjektet. Truffet Skape å skape prosjektet.




2. Oppdater Storyboard

Det første vi må gjøre er å redigere prosjektets hovedfortegnelse. Åpen Main.storyboard, velg storyboardets eneste visningskontroller, og velg Integrer inn> Navigasjons kontroller fra Redaktør Meny. Årsaken til å legge inn visningsregulatoren i en navigasjonsstyring vil bli klar senere i denne opplæringen.



3. Søk View Controller

Trinn 1: Opprett klassefiler

Som jeg nevnte i introduksjonen, for å holde ting enkelt, vil brukeren kun kunne abonnere på en podcast. La oss begynne med å opprette søkevisningsregulatoren. Å velge Ny> Fil ... fra Fil menyen og velg Mål-C klasse fra alternativene til høyre. Gi klassen navn MTSearchViewController og gjør det til en underklasse av UIViewController. La avkrysningsboksen være merket Med XIB for brukergrensesnitt ukontrollert. Fortell Xcode hvor du vil lagre klassefilene og treffe Skape.


Trinn 2: Oppdater klassegrensesnitt

Før vi oppretter brukergrensesnittet, åpner du tittelkontrollens headerfil og oppdaterer klassens grensesnitt som vist nedenfor. Vi spesifiserer at MTSearchViewController klassen stemmer overens med UITableViewDataSource, UITableViewDelegate, og UISearchBarDelegate protokoller, erklærer vi to utsalgssteder, søkelinje og Tableview så vel som en handling, Avbryt, å avvise søkevisningsregulatoren.

 #importere  @interface MTSearchViewController: UIViewController  @property (svak, ikkeatomisk) IBOutlet UISearchBar * searchBar; @property (svak, ikkeatomisk) IBOutlet UITableView * tableView; - (IBAction) avbryt: (id) avsender; @slutt

Trinn 3: Opprett brukergrensesnitt

Revisér prosjektets hovedfortegnelse og dra en ny visningscontroller fra Objektbibliotek til høyre. Velg den nye visningsregulatoren, åpne Identitetsinspektør til høyre, og sett visningskontrollens klasse til MTSearchViewController. Med den nye visningskontrollen fortsatt valgt, åpner du Redaktør menyen og velg Integrer inn> Navigasjons kontroller. Dra en tabellvisning til visningskontrollørens visning og koble tabellvisningen datakilde og delegat utsalgssteder med søk visning kontrolleren.


Når tabellvisningen fortsatt er valgt, åpner du Attributtsinspektør, og sett antall prototypeceller til 1. Velg prototypecellen og sett stilegenskapen til Subtitle og dens identifikator til SearchCell.


Dra en søkefelt fra Objektbibliotek og legg den til i tabellvisningens toppvisning. Velg søkefeltet og koble til det delegat uttak med visningsregulatoren.


Velg visningsregulatoren og koble den til søkelinje og Tableview uttak med henholdsvis søkelinjen og tabellvisningen. Det er noen andre ting vi må gjøre før vi er ferdige med storyboardet.

Åpne Objektbibliotek og dra et bar-knappelement til navigasjonslinjen. Velg barknappelementet, koble det til med Avbryt: handling vi erklærte i grensesnittet for søkevisningskontrollen, og endre dens Identifier i Attributtsinspektør til Avbryt.


Dra et barknappelement til navigasjonslinjen på visningsregulatoren (ikke søkevisningsregulatoren) og endre dens Identifier i Attributtsinspektør til Legg til. Kontroller dra fra bar-knappelementet til navigasjonskontrollen for søkvisningskontrollen og velg modal fra menyen som dukker opp. Dette skaper en segue fra visningsregulatoren til navigasjonskontrollen i søkevisningskontrollen.

Hvis du skulle kontrollere å dra av visningsregulatorens barknappelement direkte til søkevisningsregulatoren i stedet for navigasjonsstyringen, ville navigasjonskontrollen aldri bli instantiated, og du vil ikke se en navigeringslinje øverst i søkevisningsregulatoren.

Trinn 4: Implementering av tabellvisning

Før vi implementerer UITableViewDataSource og UITableViewDelegate protokoller i MTSearchViewController klasse, må vi deklarere en eiendom som lagrer søkeresultatene, vi kommer tilbake fra iTunes Search API. Navn på eiendommen podcaster som vist under. Vi erklærer også en statisk streng som vil fungere som en cellegenbruk-identifikator. Det tilsvarer identifikatoren vi satt på prototypecellen for noen få øyeblikk siden.

 #import "MTSearchViewController.h" @interface MTSearchViewController () @property (sterk, ikkeatomisk) NSMutableArray * podcasts; @slutt
 statisk NSString * SearchCell = @ "SearchCell";

Gjennomføringen av numberOfSectionsInTableView: er så enkelt som det blir. Vi returnerer 1 hvis self.podcasts er ikke nil og 0 hvis det er. Gjennomføringen av Tableview: numberOfRowsInSection: er ganske lik som du kan se nedenfor. I Tableview: cellForRowAtIndexPath:, Vi spør tabellvisningen for en celle ved å sende cellegenbrukeridentifikatoren, som vi erklærte tidligere, og indexPath. Vi henter det tilsvarende elementet fra podcaster datakilde og oppdater tabellvisningscellen. Både Tableview: canEditRowAtIndexPath: og Tableview: canMoveRowAtIndexPath: komme tilbake NEI.

 - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.podcasts? 1: 0; 
 - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) seksjon return self.podcasts? self.podcasts.count: 0; 
 - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * celle = [tableView dequeueReusableCellWithIdentifier: SearchCell forIndexPath: indexPath]; // Hent podcast NSDictionary * podcast = [self.podcasts objectAtIndex: indexPath.row]; // Konfigurer tabellvisning Cell [cell.textLabel setText: [podcast objectForKey: @ "collectionName"]]; [cell.detailTextLabel setText: [podcast objectForKey: @ "artistName"]]; returcelle; 
 - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO; 
 - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO; 

Før du kjører programmet, implementer du Avbryt: handling der vi avviser søkevisningsregulatoren.

 - (IBAction) avbryt: (id) avsender [self dismissViewControllerAnimated: JA fullføring: null]; 

Bygg prosjektet og kjør programmet for å sikre at fundamentet virker som forventet. Det er på tide å begynne å bruke NSURLSession API for å spørre iTunes Search API.

Trinn 5: Opprette en sesjon

La oss begynne med å erklære ytterligere to private eiendommer i MTSearchViewController klasse, økt og dataTask. De økt variabel brukes til å lagre en referanse til NSURLSession eksempel vi bruker for å spørre Apples API. Vi holder også en referanse til dataoppgaven vi vil bruke til forespørselen. Dette vil gjøre det mulig for oss å avbryte dataoppgaven dersom brukeren oppdaterer søket før vi har mottatt et svar fra API-en. Hvis du har øye med detaljer, har du kanskje lagt merke til at MTSearchViewController klassen overholder også UIScrollViewDelegate protokoll. Årsaken til dette vil bli klart om noen få minutter.

 #import "MTSearchViewController.h" @interface MTSearchViewController ()  @property (strong, nonatomic) NSURLSession * økt; @property (strong, nonatomic) NSURLSessionDataTask * dataTask; @property (strong, nonatomic) NSMutableArray * podcasts; @slutt

Økten er opprettet i sin getter-metode som du kan se nedenfor. Implementeringen bør ikke holde noen overraskelser hvis du har lest de tidligere opplæringene. Vi overstyrer gettermetoden til økt egenskap for å lazily laste økten og begrense øktens instantiation og konfigurasjon i sin getter metode. Dette gir ren og elegant kode.

 - (NSURLSession *) økt if (! _Session) // Initialiser Session Configuration NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Konfigurer sesjonskonfigurasjon [sessionConfiguration setHTTPAdditionalHeaders: @ @ "Accept": @ "application / json"]; // Initialiser økt _session = [NSURLSession sessionWithConfiguration: sessionConfiguration];  tilbake _session; 

Trinn 6: Søker

For å svare på brukerens innspill i søkefeltet, implementerer vi searchbar: textDidChange: av UISearchBarDelegate protokoll. Gjennomføringen er enkel. Hvis search er nil, Metoden vender tilbake tidlig. Hvis lengden på search er mindre enn fire tegn langt, tilbakestiller vi søket ved å påkalle resetSearch. Hvis spørringen er fire tegn eller lengre, utfører vi et søk ved å ringe performSearch på søkevisningsregulatoren.

 - (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchText if (! searchText) returnere; hvis (searchText.length <= 3)  [self resetSearch];  else  [self performSearch];  

Før vi inspiserer performSearch, la oss ta en rask titt på resetSearch. Alt vi gjør i resetSearch er å rydde innholdet i podcaster og laster opp tabellvisningen.

 - (void) resetSearch // Oppdater datakilde [self.podcasts removeAllObjects]; // Oppdater tabellvisning [self.tableView reloadData]; 

Den tunge løftingen er ferdig i performSearch. Etter lagring av brukerens inngang i en variabel som heter spørsmål, vi sjekker om dataTask er satt. Hvis det er satt, ringer vi Avbryt på den. Dette er viktig fordi vi ikke vil motta et svar fra en gammel forespørsel som kanskje ikke lenger er relevant for brukeren. Dette er også grunnen til at vi bare har en aktiv datapost på en gang. Det er ingen fordel i å sende flere forespørsler til API.

Deretter spør vi økten om en ny dataoppgaveeksempel ved å sende den en NSURL eksempel og en ferdigstillingshåndterer. Husk at økten er fabrikken som skaper oppgaver. Du bør aldri lage oppgaver selv. Hvis vi får en gyldig dataoppgave fra økten, ringer vi gjenoppta på det som vi så i de foregående opplæringene.

Logikken inne i ferdigstillingshåndteringen er interessant å si mildt. De feil objekt er viktig for oss av flere grunner. Ikke bare vil det fortelle oss om noe gikk galt med forespørselen, men det er også nyttig for å avgjøre om dataoppgaven ble kansellert. Hvis vi får et feilobjekt, kontrollerer vi om feilkoden er lik -999. Denne feilkoden indikerer at dataoppgaven ble kansellert. Hvis vi får en annen feilkode, logger vi feilen til konsollen. I en ekte applikasjon må du forbedre feilhåndteringen og varsle brukeren når en feil blir kastet.

Hvis ingen feil ble sendt til fullføringsbehandleren, oppretter vi en ordliste fra NSData eksempel som ble sendt til fullføringshandleren, og vi trekker ut resultatene fra det. Hvis vi har en rekke resultater å jobbe med, sender vi det videre til processResults:. Har du lagt merke til at vi påkalte processResults: i en GCD (Grand Central Dispatch) blokk? Hvorfor gjorde vi det? Jeg håper du husker, fordi det er en veldig viktig detalj. Vi har ingen garanti for at ferdigstillingsbehandleren er påkalt på hovedtråden. Siden vi trenger å oppdatere tabellvisningen på hovedtråden, må vi sørge for at processResults: kaller på hovedtråden.

 - (void) performSearch NSString * query = self.searchBar.text; hvis (self.dataTask) [self.dataTask avbryt];  self.dataTask = [self.session dataTaskWithURL: [self urlForQuery: query] completionHandler: ^ (NSData * data, NSURLResponse * respons, NSError * feil) if (error) if (error.code! =999)  NSLog (@ "% @", feil);  ellers NSDictionary * result = [NSJSONSerialization JSONObjectWithData: dataalternativer: 0 feil: null]; NSArray * results = [result objectForKey: @ "results"]; dispatch_async (dispatch_get_main_queue (), ^ if (resultater) [selvprosessResultater: resultater];); ]; hvis (self.dataTask) [self.dataTask gjenoppta]; 

Før vi ser på implementeringen av processResults:, Jeg vil raskt vise deg hva som skjer i urlForQuery:, hjelperen vi bruker i performSearch. I urlForQuery:, Vi erstatter alle mellomrom med a + logg for å sikre at iTunes Search API er fornøyd med det vi sender det. Vi lager deretter en NSURL Installer med det og returner det.

 - (NSURL *) urlForQuery: (NSString *) spørring query = [spørre strengByReplacingOccurrencesOfString: @ "" withString: @ "+"]; returnere [NSURL URLWithString: [NSString stringWithFormat: @ "https://itunes.apple.com/search?media=podcast&entity=podcast&term=%@", spørring]]; 

I processResults:, de podcaster variabel er slettet, befolket med innholdet i resultater, og resultatene vises i tabellvisningen.

 - (void) processResults: (NSArray *) resultater if (! self.podcasts) self.podcasts = [NSMutableArray array];  // Oppdater datakilde [self.podcasts removeAllObjects]; [self.podcasts addObjectsFromArray: resultater]; // Oppdater tabellvisning [self.tableView reloadData]; 

Trinn 6: Velge en podcast

Når brukeren tapper en rad i tabellvisningen for å velge en podcast, Tableview: didSelectRowAtIndexPath: av UITableViewDelegate protokollen er påkalt. Implementeringen kan virke merkelig i begynnelsen, så la meg forklare hva som skjer. Vi velger podcasten som tilsvarer brukerens valg, lagrer den i programmets brukerstandarddatabase og avviser søkevisningsregulatoren. Vi underretter ikke noen om dette? Hvorfor vi gjør dette, vil bli klart når vi fortsetter å implementere MTViewController klasse.

 - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath [tableView deselectRowAtIndexPath: indexPath animert: YES]; // Hent podcast NSDictionary * podcast = [self.podcasts objectAtIndex: indexPath.row]; // Oppdater User Defatuls NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; [ut setObject: podcast forKey: @ "MTPodcast"]; [synkronisere] // Avvis View Controller [self dismissViewControllerAnimated: JA ferdigstillelse: null]; 

Trinn 7: Etterbehandling

Det er to detaljer jeg vil snakke om før jeg kommer tilbake til MTViewController klasse. Når søkevisningsregulatoren presenteres for brukeren, er det klart at hun vil søke etter podcaster. Det er derfor en god ide å umiddelbart presentere tastaturet. Vi gjør dette inn viewDidAppear: som vist under.

 - (void) viewDidAppear: (BOOL) animert [super viewDidAppear: animated]; // Show Keyboard [self.searchBar becomeFirstRespesponder]; 

Klaviaturet må gjemme øyeblikket brukeren begynner å rulle gjennom søkeresultatene. For å oppnå dette, implementerer vi scrollViewDidScroll: av UIScrollViewDelegate protokoll. Dette forklarer hvorfor MTSearchViewController samsvarer med UIScrollViewDelegate protokoll. Se på implementeringen av scrollViewDidScroll: Vist under.

 - (void) scrollViewDidScroll: (UIScrollView *) scrollView if ([self.searchBar isFirstResponder]) [self.searchBar resignFirstResponder]; 
De UITableView klassen er en underklasse av UIScrollView, som er grunnen til at ovennevnte tilnærming fungerer.

4. Looping Back

Som vi så tidligere, lagrer vi brukerens valg i programmets brukerstandarddatabase. Vi må oppdatere MTViewController klassen for å gjøre bruk av brukerens valg i søkevisningsregulatoren. I visningsregulatorens viewDidLoad Metode, vi laster podcasten fra brukerstandarddatabasen og vi legger til visningsregulatoren som en observatør av brukerens standarddatabase for nøkkelbanen MTPodcast slik at visningskontrolleren blir varslet når verdien for MTPodcast Endringer.

 - (void) viewDidLoad [super viewDidLoad]; // Last podcast [self loadPodcast]; // Legg til observatør [[NSUserDefaults standardUserDefaults] addObserver: selv forKeyPath: @ "MTPodcast" alternativer: NSKeyValueObservingOptionNew kontekst: NULL]; 

Alt vi gjør i loadPodcast lagrer verdien for MTPodcast fra brukerens standarddatabase i visningsregulatorens podcast eiendom. Denne verdien vil være nil hvis brukerens standarddatabase ikke inneholder en oppføring for MTPodcast. Utsiktskontrollen håndterer dette med glede for oss. Husk at i Mål-C kan du sende meldinger til nil uten at helvete bryter løs. Dette har sine ulemper, men det har dessuten fordeler med.

 - (ugyldig) loadPodcast NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; self.podcast = [ut objectForKey: @ "MTPodcast"]; 

Dette betyr også at vi må deklarere en eiendom som heter podcast i visningsregulatorens implementeringsfil.

 #import "MTViewController.h" @interface MTViewController () @property (sterk, ikkeatomisk) NSDictionary * podcast; @slutt

La oss også ta en rask titt på setPodcast: og updateView.

 - (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Oppdater Vis [self updateView]; 
 - (void) updateView // Oppdater Vis self.title = [self.podcast objectForKey: @ "collectionName"]; 

Når verdien i brukerens standarddatabase endres for nøkkelen MTPodcast, visningskontrolleren kan svare på denne endringen i observeValueForKeyPath: ofObject: endring: kontekst:. Det er slik nøkkelverdi observere fungerer. Alt vi gjør i denne metoden er å oppdatere verdien av visningscontrollerens podcast eiendom.

 - (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) objekt endring: (NSDictionary *) endre kontekst: (void *) kontekst if ([keyPath isEqualToString: @ "MTPodcast"]) self.podcast = [objekt objectForKey: @ "MTPodcast"]; 

Når man arbeider med nøkkelverdi observerer, er det viktig å være oppmerksom på minnestyring og beholde sykluser. I dette tilfellet betyr det at vi må fjerne visningskontrollen som observatør når visningsregulatoren er allokert.

 - (void) dealloc [[NSUserDefaults standardUserDefaults] removeObserver: selv forKeyPath: @ "MTPodcast"]; 

5. Henting og analyse av strømmen

Trinn 1: Legge til avhengigheter

Responsen vi kommer tilbake fra iTunes Search API inneholder en feedurl attributt for hver podcast. Vi kunne manuelt hente fôret og analysere det. For å spare litt tid bruker vi imidlertid MWFeedParser, et populært bibliotek som kan gjøre dette for oss. Du kan manuelt laste ned og inkludere biblioteket i prosjektet ditt, men jeg skal velge Cocoapods. Jeg foretrekker Cocoapods for å administrere avhengigheter i IOS og OS X-prosjekter. Du kan lese mer om Cocoapods på nettstedet eller på Mobiletuts+.

Jeg kommer til å anta at Cocoapods perlen er installert på systemet ditt. Du finner detaljerte instruksjoner i denne opplæringen.

Avslutt Xcode, naviger til roten til Xcode-prosjektet, og opprett en fil som heter Podfile. Åpne denne filen i valgfri tekstredigerer og legg til følgende tre linjer med kode. I den første linjen spesifiserer vi plattformen og distribusjonsmålet, som er iOS 7 i dette eksemplet. De to neste linjene angir hver avhengighet av vårt Xcode-prosjekt. Den første er MWFeedParser bibliotek og jeg har også inkludert den populære SVProgressHUD bibliotek, som kommer til nytte litt senere.

 plattform: ios, '7' pod 'MWFeedParser' pod 'SVProgressHUD'

Åpne et terminalvindu, naviger til roten til Xcode-prosjektet, og kjør kommandoen pod installasjon. Dette bør installere avhengighetene og opprette et Xcode arbeidsområde. Når Cocoapods er ferdig med å installere prosjektets avhengigheter, forteller det deg å bruke arbeidsområdet det opprettet for deg. Dette er viktig, så ikke ignorere dette rådet. I roten til Xcode-prosjektet ser du at Cocoapods faktisk har opprettet et Xcode-arbeidsområde for deg. Dobbeltklikk denne filen, og du bør være klar til å gå.


Trinn 2: Henting og analyse av strømmen

Åpne implementeringsfilen til MTViewController klasse, legg til en importerklæring for MWFeedParser og SVProgressHUD, og erklære to egenskaper, episoder og feedParser. Vi må også gjøre MTViewController i samsvar med MWFeedParserDelegate protokollen.

 #import "MTViewController.h" #import "MWFeedParser.h" #import "SVProgressHUD.h" @interface MTViewController ()  @property (sterk, ikkeatomisk) NSDictionary * podcast; @property (strong, nonatomic) NSMutableArray * episoder; @property (strong, nonatomic) MWFeedParser * feedParser; @slutt

Deretter oppdaterer vi setPodcast: ved å påkalle fetchAndParseFeed, en hjelpemetode der vi bruker MWFeedParser klassen for å hente og analysere podcastens feed.

 - (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Oppdater Vis [self updateView]; // Hent og tolk feed [self fetchAndParseFeed]; 

I fetchAndParseFeed, vi blir kvitt vår nåværende MWFeedParser eksempel hvis vi har en og initialiser en ny forekomst med podcastens feed-URL. Vi satte feedParseType eiendom til ParseTypeFull og sett visningskontrolleren som feedsparserens delegat. Før vi henter feedet, bruker vi SVProgressHUD for å vise fremdrift HUD til brukeren.

 - (void) fetchAndParseFeed if (! self.podcast) tilbake; NSURL * url = [NSURL URLWithString: [self.podcast objectForKey: @ "feedUrl"]]; hvis (! url) returnerer; hvis (self.feedParser) [self.feedParser stopParsing]; [self.feedParser setDelegate: null]; [self setFeedParser: null];  // Klare episoder hvis (self.episodes) [self setEpisodes: null];  // Initialiser Feed Parser self.feedParser = [[MWFeedParser allok] initWithFeedURL: url]; // Konfigurer Feed Parser [self.feedParser setFeedParseType: ParseTypeFull]; [self.feedParser setDelegate: self]; // Vis fremgang HUD [SVProgressHUD showWithMaskType: SVProgressHUDMaskTypeGradient]; // Start Parsing [self.feedParser parse]; 

Vi må også implementere to metoder for MWFeedParserDelegate protokollen, feedParser: didParseFeedItem: og feedParserDidFinish:. I feedParser: didParseFeedItem:, vi initialiserer episoder Egenskap om nødvendig, og send det fôrelementet som fôrparseren hender til oss.

 - (void) feedParser: (MWFeedParser *) parser didParseFeedItem: (MWFeedItem *) element if (! self.episodes) self.episodes = [NSMutableArray array];  [self.episodes addObject: item]; 

I feedParserDidFinish:, Vi avviser fremdriften HUD og oppdaterer tabellvisningen. Sa du bordvisning? Det er riktig. Vi må legge til en tabellvisning og implementere nødvendige UITableViewDataSource protokollmetoder.

 - (void) feedParserDidFinish: (MWFeedParser *) parser // Dismiss Progress HUD [SVProgressHUD avskedig]; // Oppdater visning [self.tableView reloadData]; 

Trinn 3: Viser feedet

Før vi oppdaterer brukergrensesnittet, åpnes MTViewController.h, erklære et uttak for tabellvisningen, og fortell kompilatoren på MTViewController klassen stemmer overens med UITableViewDataSource og UITableViewDelegate protokoller.

 #importere  @interface MTViewController: UIViewController  @property (svak, ikkeatomisk) IBOutlet UITableView * tableView; @slutt

Åpne hovedfortegnelsen en gang til, og legg til en tabellvisning til visningskontrollørens visning. Koble tabellvisningen datakilde og delegat uttak med visningskontrolleren og koble til visningskontrolleren Tableview uttak med tabellvisning. Velg tabellvisningen, åpne Attributtsinspektør, og sett antall prototypeceller til 1. Velg prototypecellen, sett stilen til Subtitle, og gi den en identifikator av EpisodeCell.


Før vi implementerer UITableViewDataSource protokoll, erklære en statisk streng som heter EpisodeCell i MTViewController.m. Dette tilsvarer identifikatoren vi satt for prototypecellen i storyboardet.

 statisk NSString * EpisodeCell = @ "EpisodeCell";

Gjennomføring av UITableViewDataSource protokollen er enkel som kake og ligner på hvordan vi implementerte protokollen i søkevisningsregulatoren. Den eneste forskjellen er at episoder variabel inneholder forekomster av MWFeedItem klasse i stedet for NSDictionary forekomster.

 - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.episodes? 1: 0; 
 - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) seksjon return self.episodes? self.episodes.count: 0; 
 - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * celle = [tableView dequeueReusableCellWithIdentifier: EpisodeCell forIndexPath: indexPath]; // Hent feed element MWFeedItem * feedItem = [self.episodes objectAtIndex: indexPath.row]; // Konfigurer tabellvisningssel [cell.textLabel setText: feedItem.title]; [cell.detailTextLabel setText: [NSString stringWithFormat: @ "% @", feedItem.date]]; returcelle; 
 - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO; 
 - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO; 

Kjør programmet i iOS-simulatoren eller på en fysisk enhet og kjør den gjennom sine skritt. Du bør nå kunne søke etter podcaster, velge en podcast fra listen, og se episodene.


Konklusjon

Vi har gjort mye i denne opplæringen, men vi har fortsatt litt arbeid foran oss. I den neste opplæringen zoomer vi inn på nedlasting av episoder fra feedet, og vi diskuterer nedlastinger i bakgrunnen eller utenom prosessen. Følg med.