Nettverk er vanskelig. Det er ulike bevegelige deler involvert, og mange faktorer må vurderes for å få det til å fungere. Heldigvis har en rekke åpen kildekodebibliotek kommet fram over tid for å gjøre nettverket enklere. AFNetworking, opprettet og vedlikeholdt av folket i Gowalla, er et slikt bibliotek. Denne opplæringen vil introdusere deg til AFNetworking-rammen, samtidig som du viser hvordan du kan spørre iTunes Store API!
I denne opplæringen vil jeg introdusere deg til AFNetworking og vise deg et glimt av hva dette biblioteket har å tilby. Etter å ha brukt noen få minutter med dette biblioteket, vil du legge merke til at den ble designet med enkel bruk i tankene. Det vil ikke bare øke utviklingen din, men det vil også ta vare på mange omhyggelige nettverksoppgaver. Vi vil bygge et enkelt program som spør etter iTunes Store for filmer som samsvarer med søkeordet "harry". Resultatene av spørringen vil bli vist i en tabellvisning.
Programmet vi skal bygge spørringer i iTunes Store Search API. Spesielt søker vi i iTunes Store for filmer som samsvarer med søkeordet "harry". Hvis spørringen vår lykkes, behandler vi resultatene og viser dem i en tabellvisning. Hver rad representerer en film med tittel, regissør og et miniatyrbilde som viser filmteksten. Klar? La oss komme i gang.
Før vi får våre hender skitne med AFNetworking, må vi bygge et grunnleggende grunnlag. Dette betyr å sette opp prosjektet vårt, lage en tabellvisning og legge til en aktivitetsindikatorvisning. Vi viser aktivitetsindikatoren når vår forespørsel behandles av iTunes Store. Dette vil gi brukeren den verdifulle ekstra bit av tilbakemelding som ofte overses.
Opprett et nytt prosjekt i Xcode ved å velge Enkeltvisningsprogram mal fra listen over maler. Navn søknaden din NetworkingIsFun, skriv inn en bedriftsidentifikator, sett "iPhone" for enhetsfamilien, og fjern merket "Bruk Storyboards". Du kan la resten stå uberørt, men sørg for at Bruk automatisk referansetelling er sjekket. Fortell Xcode hvor du vil lagre prosjektet ditt og trykk "Lagre".
Selv om Interface Builder er flott, bygger jeg ofte grensesnittene mine programmatisk, og det er det vi vil gjøre i denne opplæringen også. Det vil tillate oss å bare fokusere på koden uten å bli distrahert av Interface Builder. Åpen ViewController.h og opprett tre instansvariabler (ivars) samt egenskaper for disse ivars. Siden vi skal jobbe med en tabellvisning, må du ikke glemme å gjøre visningsstyreren din i overensstemmelse med UITableViewDataSource og UITableViewDelegate protokoller. Visningsregulatorens headerfil skal nå se ut som den nedenfor:
#importere@interface ViewController: UIViewController UITableView * _tableView; UIActivityIndicatorView * _activityIndicatorView; NSArray * _movies; @property (nonatomic, behold) UITableView * tableView; @property (nonatomic, behold) UIActivityIndicatorView * activityIndicatorView; @property (nonatomic, behold) NSArray * filmer; @slutt
Hvis du er forvirret av bruk av underskrifter, anbefaler jeg at du leser om det her. Ta gjerne understreket hvis du tror det ser stygg ut eller gjør deg ubehagelig. Bortsett fra underskrifter, bør det ikke være noen overraskelser. Vi erklærer vår UITableView og UIActivityIndicatorView, samt en NSArray, som vi skal bruke til å lagre resultatene som vi kommer tilbake fra søket vårt. Klar? La oss gå over til vår visningskontrollers implementeringsfil.
Siden vi erklærte tre egenskaper i vår headerfil, må vi syntetisere deres accessorer i ViewController.m. Igjen, hvis understrekkene forvirrer deg, kan du legge dem ut.
@synthesize tableView = _tableView, activityIndicatorView = _aktivitetIndicatorView, movies = _movies;
I vår viewDidLoad metode, satte vi opp våre tabell- og aktivitetsindikatorvisninger. Koden under skal være selvforklarende for det meste. Hvis du aldri har opprettet en tabellvisning uten å bruke Interface Builder, ser du kanskje noen linjer som ikke er kjent for deg. I stedet for å koble bordvisningen i Interface Builder, tar vi oss av dette i viewDidLoad metode. Etter å ha ringt superklassen ' viewDidLoad Metode, vi initierer vår tabellvisning med en ramme og en stil, og vi stiller vår kontroller som datakilde og delegerer i tabellvisningen. Når søknaden lanseres, skjuler vi tabellvisningen vår siden vi ikke har noe å vise så lenge forespørselen ikke har returnert noen resultater. Før du legger til tabellvisningen som et undervisning i visningskontrollens visning, setter vi sin autoresiseringsmaske. Den autoresiserende masken definerer hvordan tabellvisningen skal endres hvis foreldrevisningen - visningen kontrollerens visning som vi legger til tabellvisningen - endres i størrelse. Dette skjer når enheten roteres, for eksempel. Forvirret? Ikke bekymre deg for det. Det er ikke viktig for denne applikasjonen.
- (void) viewDidLoad [super viewDidLoad]; // Sette opp tabellvisning self.tableView = [[UITableView alloc] initWithFrame: CGRectMake (0.0, 0.0, self.view.bounds.size.width, self.view.bounds.size.height) stil: UITableViewStylePlain]; self.tableView.dataSource = selv; self.tableView.delegate = self; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.tableView.hidden = YES; [self.view addSubview: self.tableView]; // Sette opp aktivitetsindikator View self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]; self.activityIndicatorView.hidesWhenStopped = JA; self.activityIndicatorView.center = self.view.center; [self.view addSubview: self.activityIndicatorView]; [self.activityIndicatorView startAnimating]; // Initialisering av datakilde self.movies = [[NSArray alloc] init];
Det er like enkelt å sette opp aktivitetsindikatorvisningen. Vi initialiserer aktivitetsindikatorvisningen med en forhåndsdefinert stil, sett dens hidesWhenStopped eiendom til JA, og plasser den i midten av sin overordnede visning. Etter at du har lagt den til visningskontrollørens visning, begynner vi å animere aktivitetsindikatoren. Aktivitetsindikatoren vil automatisk vise seg selv siden vi har satt den hidesWhenStopped eiendom til JA.
På slutten av vår viewDidLoad metode, vi initialiserer filmer array. Vi bruker det senere for å lagre resultatene av søket vårt.
For denne opplæringen vil vi bare implementere to metoder for tabellvisning datakilde protokollen. Begge disse metodene kreves. Dette er minimumsimplementeringen som kreves for å få vår tabellvisning oppe. Selv om vi har satt vår kontroller som tabelloversiktens delegat, vil vi ikke bruke noen av delegatemetoder i vår søknad. Hvis du har brukt en tabellvisning før, vil du ikke finne noen overraskelser i metoden implementeringer vist nedenfor.
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) seksjon if (self.movies && self.movies.count) return self.movies.count; ellers return 0; - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath statisk NSString * cellID = @ "Cell Identifier"; UITableViewCell * celle = [tableView dequeueReusableCellWithIdentifier: cellID]; hvis (! celle) celle = [[UITableViewCell allokere] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: cellID]; returcelle;
I Tableview: numberOfRowsInSection:, Vi må returnere antall rader i hver del av tabellvisningen. I vårt eksempel inneholder tabellvisningen bare en seksjon (standard), noe som gjør alt litt enklere. Først sjekker vi om vår filmer variabel er ikke null og vi bekrefter at den inneholder elementer. Hvis begge disse kravene er oppfylt, returnerer vi antall elementer i filmen, hvis ikke, returnerer vi null.
Våre Tableview: cellForRowAtIndexPath: metoden er også grunnleggende. Vi begynner med å spørre tabelloversikten om det er en celle vi kan gjenbruke. Hvis dette ikke er tilfelle, oppretter vi en ny celle med en stil og gjenbrukskode. Vi avslutter implementeringen vår ved å returnere cellen vår. Dette vil gjøre for nå. Du kan nå bygge og kjøre din søknad. Hvis du fulgte trinnene riktig, bør du se aktivitetsindikatoren spinne som gal og tabellvisningen skal være skjult.
Å legge til AFNetworking på prosjektet ditt er enkelt som paj. Start med å laste ned biblioteket fra GitHub og hent ut arkivet. Arkivet inneholder en mappe som heter AFNetworking, som inneholder kildefilene vi må inkludere i vårt prosjekt. Dra hele denne mappen til Xcode-prosjektet, og kontroller at du sjekker Kopier elementer i målgruppenes mappe (om nødvendig) og legg kildefilene til målet ditt også.
Etter at du har lagt til AFNetworking-biblioteket i prosjektet ditt, bygg og kjør programmet og se ettersom alt faller fra hverandre. Hva skjedde med prosjektet vårt? Hvorfor får vi alle disse advarslene og feilene? Da vi opprettet vårt Xcode-prosjekt, aktiverte vi Automatisk referansetelling (ARC). På tidspunktet for skriving bruker ikke AFNetworking-biblioteket ARC. Ikke bekymre deg, men vi kan fortsatt bruke dette ryddige biblioteket med svært liten innsats. Alt vi trenger å gjøre er å fortelle kompilatoren at alle kildefilene i AFNetworking-biblioteket ikke bruker ARC. Det er det.
Hvordan gjør vi dette? Velg prosjektet ditt i Prosjektnavigator og velg målet ditt. Klikk på Bygg faser kategorien i toppnavigasjonen og åpne Kompilere kilder skuff. Denne tabellen viser alle kildefilene kompilatoren skal kompilere ved kompileringstid. Den venstre kolonnen viser navnene på filene og den høyre kolonnen viser flaggene kompilatoren bør vite om.
Du kan se disse flaggene som instruksjoner eller meldinger til kompilatoren. Alt du trenger å gjøre er å legge til et kompilatorflagg for hver kildefil i AFNetworking-biblioteket. For å gjøre dette, velg en kildefil fra listen og dobbeltklikk cellen i den høyre kolonnen. Det vises et lite vindu der du kan legge til en eller flere kompilatorflagger. I vårt tilfelle, bare skriv inn -FNO-objc-arc og klikk Ferdig. Dette flagget forteller kompilatoren at kildefilen ikke bruker ARC. Pass på at du legger til dette flagget for alle ti kildefiler i AFNetworking-biblioteket.
AFNetworking er et bibliotek som kan gjøre mye for deg, men i dag kommer vi bare til å benytte seg av to flotte funksjoner. Før vi kan begynne å bruke AFNetworking-klassene, må vi legge til følgende importoppgave like under den første importoppgaven i visningscontrollerens implementasjonsfil.
#import "AFNetworking.h"
Denne importerklæringen gir oss tilgang til alle AFNetworking-klassene. Gå tilbake til visningsansvarlig viewDidLoad metode og legg til følgende utdrag umiddelbart etter initialiseringen av filmer matrise.
NSURL * url = [[NSURL alloc] initWithString: @ "http://itunes.apple.com/search?term=harry&country=us&entity=movie"]; NSURLRequest * request = [[NSURLRequest alloc] initWithURL: url]; AFJSONRequestOperation * operation = [AFJSONRequestOperation JSONRequestOperationWithRequest: forespørsel suksess: ^ (NSURLRequest * request, NSHTTPURLResponse * respons, id JSON) NSLog (@ "% @", JSON); feil: ^ (NSURLRequest * request, NSHTTPURLResponse * respons, NSError * feil, id JSON) NSLog (@ "Forespørsel mislyktes med feil:% @,% @", feil, error.userInfo); ]; [operasjonsstart];
La meg forklare hva som skjer. I første linje lager vi NSURL for vår forespørsel. Strengen vi bruker i initialiseringen, samsvarer med formatet som iTunes Store Search API forventer. Syntaxen til Search API er ganske enkel: Begrepet vi søker etter er "harry", vi begrenser vårt søk til den amerikanske iTunes Store, og vi ser bare på filmer. Lett, Høyre?
Deretter starter vi en NSURLRequest og passerer i NSURL vi nettopp har opprettet. Deretter går AFNetworking inn. AFNetworking inneholder noen svært spesialiserte klasser som gjør jobben vår veldig enkel. Den vi bruker her er AFJSONRequestOperation. Dette er en klasse som er utformet for å hente og analysere JSON-data i bakgrunnen. Som navnet antyder, er denne klassen en underklasse av NSOperation, eller for å være mer presis, arver en av superklassene i denne klassen fra NSOperation. Klassen lar deg hente de forespurte dataene, og den analyserer også JSON-responsen. Dette betyr at vi ikke trenger å håndtere rå JSON. Dataene du returnerer er klare til bruk i søknaden din. AFNetworking bruker den innebygde JSON-parseren på iOS 5 og faller tilbake til sin egen JSON-parser for eldre iOS-versjoner.
Det er enkelt å bruke AFJSONRequestOperation, siden det bare har én klassemetode. Denne klassemetoden aksepterer tre argumenter: (1) en NSURLRequest, (2) en suksessblokk, utført når forespørselen lykkes, og (3) en feilblokk, utført når forespørselen mislykkes. Hvis blokker er nye for deg, eller du ikke er komfortabel med å bruke dem, anbefaler jeg at du leser veiledningen av Collin Ruffenach om blokker og oppsummering på Mobiletuts +. Suksessblokken tar tre argumenter: (1) NSURLRequest, (2) NSHTTPURLResponse av vår forespørsel, og (3) et analysert JSON-objekt. Feilblokken er nesten identisk. Den eneste forskjellen er at det tar et ekstra argument, en NSError som inneholder mer informasjon om hva som gikk galt dersom vår forespørsel mislykkes.
For testformål logger vi det analyserte JSON-objektet for å se hva iTunes Store Search API sender tilbake til oss. I tillegg logger vi også feilen i feilblokken hvis vår forespørsel skjer for å mislykkes. Før du bygger og kjører programmet enda en gang, må vi starte operasjonen ved å ringe start på operasjonsobjektet. Bygg og kjør din søknad og ta en titt på utgangen i konsollen.
Hvis alt gikk bra, vil du se resultatene av vår forespørsel logget på konsollen. Det analyserte JSON-objektet er en ordbok med to nøkler: (1) RESULTCOUNT, som inneholder antall resultater returnert og (2) den faktiske resultater som en rekke ordbøker. Vi loggte ikke bare svaret på konsollen for å se om vår forespørsel var vellykket, vi kan nå se nøklene for hvert element i resultatfeltet. Vi trenger disse tastene for å vise litt informasjon i tabellvisningen.
Vi er nå klare til å vise resultatene i tabellvisningen vår. Erstatt loggoppgaven i suksessblokken med utsnittet som er vist nedenfor. Vi begynner med å tilordne resultatraden til responsobjektet til filmen. Det eneste du må gjøre er å skjule aktivitetsindikatoren ved å stoppe den, vise tabellvisningen og laste opp tabellvisningen med de nye dataene som er lagret i filmen.
self.movies = [JSON objectForKey: @ "results"]; [self.activityIndicatorView stopAnimating]; [self.tableView setHidden: NO]; [self.tableView reloadData];
Neste endrer vi Tableview: cellForRowAtIndexPath: metode. Juster implementeringen din for å gjenspeile den nedenfor. Etter at vi har oppnådd en referanse til en celle, spør vi filmenes array for riktig element, og oppdaterer etikettene til cellen med tittelen og regissøren av filmen. Bygg og kjør din søknad.
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath statisk NSString * cellID = @ "Cell Identifier"; UITableViewCell * celle = [tableView dequeueReusableCellWithIdentifier: cellID]; hvis (! celle) celle = [[UITableViewCell allokere] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: cellID]; NSDictionary * movie = [self.movies objectAtIndex: indexPath.row]; cell.textLabel.text = [movie objectForKey: @ "trackName"]; cell.detailTextLabel.text = [filmobjektForKey: @ "artistName"]; returcelle;
Du har kanskje lagt merke til at det ikke er noen miniatyrbilder å se. La oss fikse det ved å legge til tre ekstra linjer til vår Tableview: cellForRowAtIndexPath: metode. Bygg og kjør din søknad.
NSURL * url = [[NSURL alloker] initWithString: [movie objectForKey: @ "artworkUrl100"]]; NSData * data = [NSData dataWithContentsOfURL: url]; cell.imageView.image = [[UIImage alloc] initWithData: data];
Har du merket at vårt bordvisning ikke ruller jevnt. Hvorfor det? Som jeg nevnte i en tidligere opplæring, må du alltid sørge for at hovedtråden i søknaden din fortsatt er lydhør. I dagens implementering av vår Tableview: cellForRowAtIndexPath: Metode, vi laster ned miniatyrbildene på hovedtråden. Dette betyr at brukergrensesnittet ikke kan oppdateres før en forespørsel om et miniatyrbilde er ferdig. Våre miniatyrer er små, så forespørgene tar ikke for lang tid å fullføre, men forestill deg å ta samme tilnærming til større eiendeler. Brukeropplevelsen ville være forferdelig. Selv for vår enkle applikasjon er brukeropplevelsen uakseptabel. Vi kan imidlertid rette opp dette med en veldig nyttig funksjon i AFNetworking-biblioteket.
Skaperne av AFNetworking så behovet for å laste ned eiendeler i bakgrunnen også. De opprettet derfor en kategori for UIImageView. Denne kategorien lar deg laste ned bilder i bakgrunnen med kun to kodelinjer. Denne kategorien er en sann livredder. Se koden nedenfor.
NSURL * url = [[NSURL alloker] initWithString: [movie objectForKey: @ "artworkUrl100"]]; [cell.imageView setImageWithURL: url placeholderImage: [UIImage imageNamed: @ "placeholder"]];
Den første linjen med kode forblir den samme. I den andre linjen forteller vi bildetevisningen der miniatyrbildet ligger ved å sende en NSURL, og vi sender et stedholderbilde, som vises så lenge forespørselen vår ikke har returnert et svar. Hvor kult er det? Alt vi trenger å gjøre er å legge til et plassholderbilde for prosjektet vårt. Dette kan være et hvilket som helst bilde du vil ha, men du kan finne bildet jeg har brukt som plassholder i nedlastingsfilen som er vedlagt denne opplæringen. Når du har lagt til plassholderbildet, bygg og kjør programmet og test selv hvor glatt tabellvisningen ruller!
Vær oppmerksom på at applikasjonen vår er veldig grunnleggende i utførelsen, da den ikke gjør noen caching, og vi kan bare søke i iTunes Store for begrepet "harry" i filmdelen. Men med svært liten innsats kan du lage en fin applikasjon for å søke i iTunes Store på en mer dynamisk måte.
Jeg håper denne opplæringen har overbevist deg om at AFNetworking-biblioteket er et flott verktøy for å få i arsenalet ditt. Det kan gjøre mye mer enn det jeg viste deg i dette innlegget, men hovedmålet med denne opplæringen er å få deg i gang med AFNetworking og klar til å bruke den i en ekte verdenscenario.