În tutorialele anterioare, am explorat fundamentele NSURLSession
API-ul. Există o altă caracteristică a NSURLSession
API pe care nu am analizat încă, adică încărcări și descărcări în afara procesului. În următoarele două tutoriale, vă voi arăta cum să creați un client podcast foarte simplu, care să permită descărcarea fundalului.
Clientul podcast pe care urmează să-l creăm nu va fi într-adevăr funcțional. Acesta va permite utilizatorului să interogheze API-ul iTunes Search pentru o listă de podcast-uri, să selecteze un podcast și să descarce episoade. Deoarece ne concentrăm pe NSURLSession
API, nu vom intra în redarea episoadelor descărcărilor aplicațiilor.
Proiectul, cu toate acestea, vă va învăța cum să utilizați sarcinile de date și să descărcați sarcini într-o aplicație din lumea reală. Clientul podcast va permite, de asemenea, descărcări de fundal pentru care le vom folosi NSURLSession
's out-of-process API. Avem foarte puține lucruri pentru a face acest lucru, să nu pierdem timpul și să începem.
Activați Xcode 5, selectați Nou> Proiect ... de la Fişier meniu și alegeți Vizualizare individuală șablon din lista de șabloane de aplicații iOS. Denumiți aplicația Singlecast, Seteaza Familia de dispozitive la iPhone, și spuneți Xcode unde doriți să salvați proiectul. Lovit Crea pentru a crea proiectul.
Primul lucru pe care trebuie să-l facem este să editați tabloul de bord principal al proiectului. Deschis Main.storyboard, selectați controlerul vizualizării numai de la panoul de afișare și alegeți Încorporați în> Controller de navigare de la Editor meniul. Motivul pentru încorporarea controlerului de vizualizare într-un controler de navigație va deveni clar mai târziu în acest tutorial.
După cum am menționat în introducere, pentru a menține lucrurile simple, utilizatorul va putea abona la un singur podcast. Să începem prin crearea controlerului de vizualizare a căutării. Selectați Nou> Fișier ... de la Fişier meniu și alegeți Clasa obiectiv-C din opțiunile din dreapta. Denumiți clasa MTSearchViewController
și să o facă o subclasă de UIViewController
. Lăsați caseta de selectare etichetă Cu XIB pentru interfața cu utilizatorul neverificată. Spuneți Xcode unde doriți să salvați fișierele de clasă și să le loviți Crea.
Înainte de a crea interfața cu utilizatorul, deschideți fișierul de antet al controlerului de vizualizare și actualizați interfața clasei așa cum se arată mai jos. Specificăm că MTSearchViewController
clasa este conformă cu UITableViewDataSource
, UITableViewDelegate
, și UISearchBarDelegate
protocoale, declarăm două puncte de vânzare, bara de căutare
și tableView
precum și o acțiune, Anulare
, să respingă controlerul de vizualizare a căutării.
#import@interface MTSearchViewController: UIViewController @property (slab, nonatomic) IBOutlet UISearchBar * searchBar; @property (slab, nonatomic) IBOutlet UITableView * tableView; - (IBAction) anulați: (id) expeditor; @Sfârșit
Revizuiți tabloul de bord al proiectului și trageți un nou controler de vizualizare din Biblioteca de obiecte pe dreapta. Selectați noul controler de vizualizare, deschideți Inspectorul de identitate din dreapta, și setați clasa controlerului de vizualizare la MTSearchViewController
. Cu noul controler de vizualizare selectat, deschideți Editor meniu și alegeți Încorporați în> Controller de navigare. Glisați o vizualizare de tabelă în vizualizarea controlerului de vizualizare și conectați vizualizarea tabelului sursă de date
și delega
punctele de vânzare cu controler vizualizare căutare.
Cu ecranul de masă selectat încă, deschideți Atribuții Inspector, și setați numărul de celule prototip 1
. Selectați celula prototip și setați proprietatea stilului la Subtitlu și identificatorul său la SearchCell
.
Glisați o bară de căutare din Biblioteca de obiecte și adăugați-l în vizualizarea antetului tabelului. Selectați bara de căutare și conectați-o delega
priza cu controlerul de vizualizare.
Selectați controlerul de vizualizare și conectați-l bara de căutare
și tableView
ieșiri cu bara de căutare și, respectiv, tabelul. Există câteva alte lucruri pe care trebuie să le facem înainte să terminăm cu tabloul de bord.
Deschide Biblioteca de obiecte și trageți un element de buton de bare în bara de navigare. Selectați elementul butonului bara, conectați-l cu Anulare:
acțiunea pe care am declarat-o în interfața controlerului de vizualizare a căutării și o schimbăm Identificator în Atribuții Inspector la Anulare.
Glisați un element de buton de bare în bara de navigare a controlerului de vizualizare (nu în modulul de vizualizare a căutării) și schimbați-l Identificator în Atribuții Inspector la Adăuga. Trageți de la elementul butonului bară spre controlerul de navigare al controlerului de vizualizare a căutării și selectați modal din meniul care apare. Acest lucru creează o problemă de la controlerul de vizualizare la controlerul de navigare al controlerului de vizualizare a căutării.
Dacă ați controla trageți de la butonul de bare al controlerului de vizualizare direct la controlerul de vizualizare a căutării în locul controlerului de navigare, controlerul de navigație nu ar fi niciodată instanțiat și nu ați vedea o bară de navigare în partea superioară a controlerului de vizualizare a căutării.Înainte de a implementa UITableViewDataSource
și UITableViewDelegate
protocoale în MTSearchViewController
, trebuie să declarăm o proprietate care stochează rezultatele căutării pe care le vom reveni din API-ul de căutare iTunes. Denumiți proprietatea podcast-uri
așa cum se arată mai jos. De asemenea, declarăm un șir static care va servi drept identificator de reutilizare a celulelor. Aceasta corespunde identificatorului pe care l-am fixat pe celula prototip cu câteva momente în urmă.
#import "MTSearchViewController.h" @interface MTSearchViewController () @property (puternic, nonatomic) NSMutableArray * podcasturi; @Sfârșit
statică NSString * SearchCell = @ "SearchCell";
Implementarea sistemului numberOfSectionsInTableView:
este la fel de ușor pe cât se întâmplă. Ne intoarcem 1
dacă self.podcasts
nu este zero
și 0
dacă este. Implementarea sistemului tableView: numberOfRowsInSection:
este destul de asemănătoare, după cum puteți vedea mai jos. În tableView: cellForRowAtIndexPath:
, cerem vizualizarea tabelului pentru o celulă prin trecerea identificatorului de reutilizare a celulelor, pe care l-am declarat mai devreme, și indexPath
. Atragem elementul corespunzător din podcast-uri
sursă de date și să actualizați celula de vizualizare a tabelului. Ambii tableView: canEditRowAtIndexPath:
și tableView: canMoveRowAtIndexPath:
întoarcere NU
.
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.podcasts? 1: 0;
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) sectiunea return self.podcasts? auto.podcasts.count: 0;
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * celula = [tableView dequeueReusableCellWithIdentifier: SearchCell forIndexPath: indexPath]; // Descărcați Podcast NSDictionary * podcast = [auto.podcasts objectAtIndex: indexPath.row]; // Configurați tabelul de vizualizare a celulei [cell.textLabel setText: [podcast objectForKey: @ "collectionName"]]; [cell.detailTextLabel setText: [podcast objectForKey: @ "artistName"]]; celule retur;
- (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath retur NO;
- (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO;
Înainte de a rula aplicația, implementați aplicația Anulare:
acțiune în care respingem controlerul de vizualizare a căutării.
- (IBAction) anulați: (id) expeditor [self dismissViewControllerAnimated: YES finalizare: nil];
Construiți proiectul și rulați aplicația pentru a vă asigura că fundația funcționează conform așteptărilor. Este timpul să începeți să utilizați NSURLSession
API pentru a interoga API-ul de căutare iTunes.
Să începem prin a declara două proprietăți private suplimentare în MTSearchViewController
clasă, sesiune
și dataTask
. sesiune
variabila este folosită pentru a stoca o referință la NSURLSession
instanța pe care o vom folosi pentru interogarea API-ului Apple. De asemenea, ținem o referință la sarcina de date pe care o vom folosi pentru solicitare. Acest lucru ne va permite să anulam sarcina de date dacă utilizatorul actualizează interogarea de căutare înainte de a primi un răspuns de la API. Dacă aveți un ochi pentru detalii, este posibil să fi observat că MTSearchViewController
clasa este, de asemenea, conforme cu UIScrollViewDelegate
protocol. Motivul pentru aceasta va deveni clar în câteva minute.
#import "MTSearchViewController.h" @interface MTSearchViewController ()@property (puternic, nonatomic) sesiune NSURLSession *; @property (puternic, nonatomic) NSURLSessionDataTask * dataTask; @property (puternic, nonatomic) NSMutableArray * podcast-uri; @Sfârșit
Sesiunea este creată în metoda getter, după cum puteți vedea mai jos. Implementarea sa nu ar trebui să aibă surprize dacă ați citit tutorialele anterioare. Depășim metoda getter din sesiune
proprietatea de a încărca cu ușurință sesiunea și de a limita instanțiarea și configurația sesiunii în metoda getter. Acest lucru face ca un cod curat și elegant.
- (NSURLSession *) sesiune if (! _Session) // Configurarea sesiunii inițializate NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Configurați configurarea sesiunii [sessionConfiguration setHTTPAdditionalHeaders: @ @ "Accept": @ "application / json"]; // Initializați sesiunea _session = [NSURLSession sessionWithConfiguration: sessionConfiguration]; retur _session;
Pentru a răspunde la intrarea utilizatorului în bara de căutare, implementăm SearchBar: textDidChange:
din UISearchBarDelegate
protocol. Implementarea este simplă. Dacă searchText
este zero
, metoda se întoarce mai devreme. Dacă lungimea lui searchText
are mai puțin de patru caractere, resetăm căutarea invocând resetSearch
. Dacă interogarea are patru caractere sau mai mult, efectuăm o căutare prin apelare performSearch
pe controlerul de vizualizare a căutării.
- (void) searchBar: (UISearchBar *) căutareBar textDidChange: (NSString *) searchText if (! searchText) retur; dacă (searchText.length <= 3) [self resetSearch]; else [self performSearch];
Înainte de a inspecta performSearch
, Să aruncăm o privire rapidă resetSearch
. Tot ce facem resetSearch
clarifică conținutul podcast-uri
și reîncărcarea vizualizării tabelului.
- (void) resetSearch // Actualizare sursă de date [self.podcasts removeAllObjects]; // Actualizați tabelul [self.tableView reloadData];
Ridicarea greu se face în performSearch
. După stocarea intrării utilizatorului într-o variabilă numită întrebare
, verificăm dacă dataTask
este setat. Dacă este setat, sunăm Anulare
pe el. Acest lucru este important deoarece nu vrem să primim un răspuns de la un vechi solicitare care nu mai poate fi relevantă pentru utilizator. Acesta este și motivul pentru care avem o singură sarcină activă de date la un moment dat. Nu există niciun avantaj în trimiterea mai multor solicitări către API.
Apoi, solicităm sesiunii o nouă instanță de sarcini de date prin trecerea acesteia NSURL
instanță și un handler de completare. Amintiți-vă că sesiunea este fabrica care creează sarcini. Niciodată nu ar trebui să creați sarcini. Dacă primim o sarcină validă de date din sesiune, sunăm relua
așa cum am văzut în tutorialele anterioare.
Logica din cadrul procesorului de terminare este interesantă să spunem cel puțin. eroare
obiect este important pentru noi din mai multe motive. Nu numai că ne va spune dacă s-a întâmplat ceva cu cererea, dar este, de asemenea, util pentru a determina dacă sarcina de date a fost anulată. Dacă obținem un obiect de eroare, verificăm dacă codul său de eroare este egal cu -999
. Acest cod de eroare indică faptul că sarcina de date a fost anulată. Dacă primim un alt cod de eroare, vom înregistra eroarea în consolă. Într-o aplicație reală, va trebui să îmbunătățiți modul de gestionare a erorilor și să anunțați utilizatorul atunci când apare o eroare.
Dacă nu a fost transmisă nici o eroare handlerului de finalizare, vom crea un dicționar din NSData
instanță care a fost transmisă muncitorului de finalizare și extragem rezultatele din acesta. Dacă avem o mulțime de rezultate cu care să lucrăm, noi le transmitem processResults:
. Ai observat că am invocat-o processResults:
într-un bloc GCD (Grand Central Dispatch)? De ce am făcut asta? Sper că vă aduceți aminte, pentru că este un detaliu foarte important. Nu avem nici o garantie ca handlerul de completare este invocat pe firul principal. Deoarece trebuie să actualizăm vizualizarea tabelului cu privire la firul principal, trebuie să ne asigurăm că aceasta processResults:
este chemat pe firul principal.
- (void) performSearch NSString * query = auto.searchBar.text; dacă (self.dataTask) [auto.dataTask anulați]; auto.dataTask = [auto.session dataTaskWithURL: [auto urlForQuery: interogare] completionHandler: ^ (NSData * date, NSURLResponse * răspuns, eroare NSError *) if (error.code! NSLog (@ "% @", eroare); altceva NSDictionary * result = [NSJSONSerializare JSONObjectWithData: opțiuni de date: 0 eroare: zero]; NSArray * rezultate = [rezultatul obiectForKey: @ "rezultate"]; dispatch_async (dispatch_get_main_queue (), ^ dacă (rezultate) [auto processResults: results];); ]; dacă (self.dataTask) [auto.dataTask resume];
Înainte de a ne uita la punerea în aplicare a processResults:
, Vreau să vă arăt rapid ce se întâmplă urlForQuery:
, metoda de ajutor pe care o folosim performSearch
. În urlForQuery:
, noi înlocuim orice spații cu +
semnați pentru a vă asigura că API-ul de căutare iTunes este mulțumit de ceea ce îi trimitem. Apoi creăm un NSURL
instanță și returnați-o.
- (NSURL *) urlForQuery: (NSString *) interogare interogare = [interogare stringByReplacingOccurrencesOfString: @ "" cuString: @ "+"]; returnați [NSURL URLWithString: [NSString stringWithFormat: @ "https://itunes.apple.com/search?media=podcast&entity=podcast&term=%@", interogare]];
În processResults:
, podcast-uri
variabilă este șters, populate cu conținutul rezultate
, iar rezultatele sunt afișate în vizualizarea tabelului.
- (void) processResults: (NSArray *) rezultate if (! self.podcasts) self.podcasts = [NSMutableArray array]; // Actualizare sursă de date [self.podcasts removeAllObjects]; [auto.podcasts addObjectsFromArray: rezultate]; // Actualizați tabelul [self.tableView reloadData];
Când utilizatorul fixează un rând în vizualizarea tabelului pentru a selecta un podcast, tableView: didSelectRowAtIndexPath:
din UITableViewDelegate
se invocă protocolul. Implementarea lui poate părea ciudată la început, așa că permiteți-mi să explic ce se întâmplă. Selectăm podcast-ul care corespunde cu selecția utilizatorului, stochează-l în baza de date implicită pentru utilizatori și refuză controlerul de vizualizare a căutării. Nu informăm pe nimeni despre asta? De ce vom face acest lucru vor deveni clare odată ce vom continua implementarea MTViewController
clasă.
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath [tableView deselectRowAtIndexPath: indexPath animat: YES]; // Descărcați Podcast NSDictionary * podcast = [auto.podcasts objectAtIndex: indexPath.row]; // Actualizați utilizatorii Defatuți NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; [ud setObject: podcast pentruKey: @ "MTPodcast"]; [sincroniza]; // Renunțați la controlul vizualizării [self dismissViewControllerAnimated: YES completion: nil];
Sunt două detalii despre care vreau să vorbesc înainte de a reveni la MTViewController
clasă. Atunci când controlerul de vizualizare a căutării este prezentat utilizatorului, este clar că dorește să caute podcast-uri. Prin urmare, este bine să prezentați imediat tastatura. Facem asta înăuntru viewDidAppear:
așa cum se arată mai jos.
- (vid) viewDidAppear: (BOOL) animat [super viewDidAppear: animat]; // Afișați tastatura [self.searchBar becomeFirstResponder];
Tastatura trebuie să se ascundă în momentul în care utilizatorul începe să deruleze rezultatele căutării. Pentru a realiza acest lucru, implementăm scrollViewDidScroll:
din UIScrollViewDelegate
protocol. Acest lucru explică de ce MTSearchViewController
este în conformitate cu UIScrollViewDelegate
protocol. Arunca o privire la punerea în aplicare a scrollViewDidScroll:
prezentat mai jos.
- (void) scrollViewDidScroll: (UIScrollView *) scrollView dacă [[self.searchBar isFirstResponder]) [auto.searchBar resignFirstResponder];
UITableView
clasa este o subclasă de UIScrollView
, care este motivul pentru care funcționează abordarea de mai sus. După cum am văzut mai devreme, stocăm selecția utilizatorului în baza de date a aplicațiilor implicite. Trebuie să actualizăm MTViewController
pentru a utiliza selecția utilizatorului în controlerul de vizualizare a căutării. În controlerul de vizualizare viewDidLoad
, încărcăm podcastul din baza de date implicită pentru utilizatori și adăugăm controlerul de vizualizare ca observator al bazei de date implicite pentru utilizatorul pentru calea cheie MTPodcast
astfel încât controlerul de vizualizare să fie notificat atunci când valoarea pentru MTPodcast
schimbări.
- (vid) viewDidLoad [super viewDidLoad]; // Încarcă Podcast [self loadPodcast]; // Add Observer [[NSUserDefaults standardUserDefaults] addObserver: self forKeyPath: @ Opțiuni "MTPodcast": NSKeyValueObservingOptionNew context: NULL];
Tot ce facem loadPodcast
stochează valoarea pentru MTPodcast
din baza de date implicită a utilizatorilor din controlerul de vizualizare podcast
proprietate. Această valoare va fi zero
dacă baza de date implicită pentru utilizator nu conține o înregistrare pentru MTPodcast
. Controlerul de vizualizare se va ocupa gratios de aceasta pentru noi. Rețineți că, în Obiectiv-C, puteți trimite mesaje către zero
fără ca toată iadul să se despartă. Acest lucru are dezavantajele sale, dar cu siguranță are avantajele sale.
- (void) loadPodcast NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; self.podcast = [ud objectForKey: @ "MTPodcast"];
Aceasta înseamnă, de asemenea, că trebuie să declarăm o proprietate numită podcast
în fișierul de implementare a controlerului de vizualizare.
#import "MTViewController.h" @interface MTViewController () @property (puternic, nonatomic) NSDictionary * podcast; @Sfârșit
Să aruncăm o privire rapidă setPodcast:
și updateView
.
- (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Actualizare Vizualizare [self updateView];
- (void) updateView // Actualizare vizualizare self.title = [auto.podcast objectForKey: @ "collectionName"];
Când valoarea din baza de date implicită a utilizatorului modifică cheia MTPodcast
, controlerul de vizualizare poate răspunde la această modificare observeValueForKeyPath: ofObject: schimbare: Context:
. Așa funcționează observarea valorii cheie. Tot ceea ce facem în această metodă este actualizarea valorii controlerului de vizualizare podcast
proprietate.
- (void) observeValueForKeyPath: (NSString *) cheiePath ofObject: (id) modificarea obiectului: (NSDictionary *) schimbare context: (void *) context if ([keyPath esteEqualToString: @ "MTPodcast"]) self.podcast = objectForKey: @ "MTPodcast"];
Când lucrați cu respectarea valorii cheie, este esențial să fiți conștienți de gestionarea memoriei și să păstrați ciclurile. În acest caz, înseamnă că trebuie să eliminăm controlerul de vizualizare ca observator când controlerul de vizualizare este dezalocat.
- (void) dealloc [[NSUserDefaults standardUserDefaults] removeObserver: self forKeyPath: @ "MTPodcast"];
Răspunsul pe care îl primim din API-ul de căutare iTunes include a adresă url feed
atribut pentru fiecare podcast. Am putea să preluăm manual feedul și să îl analizăm. Cu toate acestea, pentru a economisi ceva timp, vom folosi MWFeedParser, o bibliotecă populară care poate face acest lucru pentru noi. Puteți să descărcați manual și să includeți biblioteca în proiectul dvs., dar voi opta pentru Cocoapods. Prefer Cocoapods pentru gestionarea dependențelor în proiectele iOS și OS X. Puteți citi mai multe despre Cocoapods pe site-ul său sau pe Mobiletuts+.
Închideți Xcode, navigați la rădăcina proiectului dvs. Xcode și creați un fișier numit Podfile. Deschideți acest fișier în editorul de text ales și adăugați următoarele trei linii de cod. În prima linie, specificăm platforma și ținta de implementare, care este iOS 7 în acest exemplu. Următoarele două linii specifică o dependență a proiectului nostru Xcode. Primul este MWFeedParser biblioteca și am inclus și popularul SVProgressHUD bibliotecă, care va veni la îndemână un pic mai târziu.
platformă: ios, '7' pod 'MWFeedParser' pod 'SVProgressHUD'
Deschideți o fereastră Terminal, navigați la rădăcina proiectului dvs. Xcode și executați comanda pod instalare
. Aceasta ar trebui să instaleze dependențele și să creeze un spațiu de lucru Xcode. Când Cocoapods este terminat, instalând dependențele proiectului, acesta vă spune să utilizați spațiul de lucru creat pentru dvs. Acest lucru este important, așa că nu ignorați acest sfat. În rădăcina proiectului dvs. Xcode, veți vedea că Cocoapods a creat într-adevăr un spațiu de lucru Xcode pentru dvs. Faceți dublu clic pe acest fișier și ar trebui să fiți gata să mergeți.
Deschideți fișierul de implementare al MTViewController
class, adăugați o declarație de import pentru MWFeedParser și SVProgressHUD, și să declare două proprietăți, episoade
și feedParser
. Trebuie, de asemenea, să facem MTViewController
în conformitate cu MWFeedParserDelegate
protocol.
#import "MTViewController.h" #import "MWFeedParser.h" #import "SVProgressHUD.h" @interface MTViewController ()@property (puternic, nonatomic) NSDictionary * podcast; @property (puternice, nonatomice) NSMutableArray * episoade; @property (puternic, nonatomic) MWFeedParser * feedParser; @Sfârșit
Apoi, actualizăm setPodcast:
invocând fetchAndParseFeed
, o metodă de ajutor în care folosim MWFeedParser
clasa pentru a prelua și analiza feed-ul podcast-ului.
- (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Actualizare Vizualizare [self updateView]; // Fetch și Parse Feed [self fetchAndParseFeed];
În fetchAndParseFeed
, scapăm de curentul nostru MWFeedParser
dacă avem unul și inițializăm o nouă instanță cu adresa URL a fluxului de podcast. Am setat feedParseType
proprietate la ParseTypeFull
și setați controlerul de vizualizare ca delegat al parserului feedului. Înainte de a prelua hrana, folosim SVProgressHUD
pentru a arăta un utilizator de progres HUD.
- (void) fetchAndParseFeed if (! self.podcast) retur; NSURL * url = [NSURL URLWithString: [auto.podcast objectForKey: @ "feedUrl"]]; dacă (! url) returnează; dacă (self.feedParser) [self.feedParser stopParsing]; [self.feedParser setDelegate: zero]; [auto setFeedParser: zero]; // Episoade clare dacă (episoade auto) [auto setEpisodes: nil]; // Initializeaza parserul feedului self.feedParser = [[MWFeedParser alloc] initWithFeedURL: url]; // Configurează parserul feedului [self.feedParser setFeedParseType: ParseTypeFull]; [self.feedParser setDelegate: self]; // Afișați progresul HUD [SVProgressHUD showWithMaskType: SVProgressHUDMaskTypeGradient]; // Începeți parsarea [self.feedParser parse];
Trebuie, de asemenea, să punem în aplicare două metode MWFeedParserDelegate
protocol, feedParser: didParseFeedItem:
și feedParserDidFinish:
. În feedParser: didParseFeedItem:
, inițializăm episoade
dacă este necesar, și să îi transmiteți elementul de alimentare pe care analizatorul feed-ului ni-l deține.
- (void) feedParser: (paragraful MWFeedParser *) didParseFeedItem: (MWFeedItem *) element if (! self.episodes) self.episodes = [NSMutableArray array]; [auto.episode addObject: element];
În feedParserDidFinish:
, renunțăm la progresul HUD și actualizăm vizualizarea tabelului. Ai spus vizualizarea tabelului? Asta e corect. Trebuie să adăugăm o vizualizare de tabel și să implementăm cerințele necesare UITableViewDataSource
metode de protocol.
- (void) feedParserDidFinish: (paragraful MWFeedParser *) // Renunțarea la progresul HUD [respingerea SVProgressHUD]; // Actualizare Vizualizare [self.tableView reloadData];
Înainte de a actualiza interfața cu utilizatorul, deschideți MTViewController.h
, declarați o priză pentru vizualizarea tabelului și informați compilatorul despre MTViewController
clasa este conformă cu UITableViewDataSource
și UITableViewDelegate
protocoale.
#import@ interfață MTViewController: UIViewController @property (slab, nonatomic) IBOutlet UITableView * tableView; @Sfârșit
Deschideți încă o dată tabloul de bord principal și adăugați o vizualizare de tabel la vizualizarea controlerului de vizualizare. Conectați vizualizarea tabelului sursă de date
și delega
ieșiți împreună cu controlerul de vizualizare și conectați controlerul de vizualizare tableView
ieșiți cu vizualizarea tabelului. Selectați vizualizarea tabelului, deschideți Atribuții Inspector, și setați numărul de celule prototip 1
. Selectați celula prototip, setați stilul acesteia Subtitlu, și dați-i un identificator de EpisodeCell.
Înainte de a implementa UITableViewDataSource
protocol, declarați un șir static numit EpisodeCell
în MTViewController.m. Aceasta corespunde cu identificatorul stabilit pentru celula prototipului din storyboard.
statică NSString * EpisodeCell = @ "EpisodeCell";
Implementarea sistemului UITableViewDataSource
protocolul este simplu ca plăcintă și foarte similar cu modul în care am implementat protocolul în controlerul de vizualizare a căutării. Singura diferență este că episoade
variabila conține instanțe ale MWFeedItem
clasă în loc de NSDictionary
instanțe.
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.episodes? 1: 0;
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) sectiunea return self.episodes? auto.episodes.count: 0;
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * celula = [tableView dequeueReusableCellWithIdentifier: EpisodeCell forIndexPath: indexPath]; // Returnați elementul Feed MWFeedItem * feedItem = [auto.episodes objectAtIndex: indexPath.row]; // Configurează tabelul de vizualizare a celulei [cell.textLabel setText: feedItem.title]; [cell.detailTextLabel setText: [NSString șirWithFormat: @ "% @", feedItem.date]]; celule retur;
- (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath retur NO;
- (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO;
Rulați aplicația în Simulatorul iOS sau pe un dispozitiv fizic și executați-o prin pașii săi. Acum ar trebui să puteți căuta podcast-uri, să selectați un podcast din listă și să vedeți episoadele sale.
Am făcut multe în acest tutorial, dar avem încă destul de mult de lucru în fața noastră. În tutorialul următor, mărim intensitatea descărcării episoadelor din feed și vom discuta descărcări de fundal sau în afara procesului. Rămâneți aproape.