Nätverk gjorde det enkelt med AFNetworking

Nätverk är svårt. Det finns olika rörliga delar inblandade och många faktorer måste övervägas för att få det att fungera. Lyckligtvis har ett antal open-source-bibliotek uppstått över tiden för att göra nätverket enklare. AFNetworking, skapad och underhållen av Gowalla, är ett sådant bibliotek. Denna handledning kommer att introducera dig till AFNetworking-ramen medan du också visar hur du frågar om iTunes Store API!

I denna handledning kommer jag att presentera dig för AFNetworking och visa dig en glimt av vad detta bibliotek har att erbjuda. Efter några minuter med det här biblioteket märker du att det var designat med enkel användning i åtanke. Det kommer inte bara att påskynda din utveckling, men det kommer också att ta hand om många noggranna nätverksuppgifter. Vi kommer att bygga en enkel applikation som frågar i iTunes Store för filmer som matchar sökordet "harry". Resultaten av vår fråga kommer att visas i en tabellvy.


Projekt sammanfattning

Applikationen som vi ska bygga förfrågningar i iTunes Store Search API. I synnerhet söker vi i iTunes Store för filmer som matchar sökordet "harry". Om vår fråga är framgångsrik bearbetar vi resultaten och visar dem i en tabellvy. Varje rad representerar en film med en titel, en regissör och en miniatyrbild som visar filmtexter. Redo? Låt oss börja.


Projektinställningar

Innan vi får våra händer smutsiga med AFNetworking, måste vi bygga en grundläggande grund. Det innebär att vi konfigurerar vårt projekt, skapar en tabellvy och lägger till en aktivitetsindikatorvy. Vi visar aktivitetsindikatorn när vår begäran behandlas av iTunes Store. Detta ger användaren den värdefulla extra bit av feedback som ofta förbises.

Skapa ett nytt projekt i Xcode genom att välja Enkel visningsprogram mall från listan med mallar. Namn på din ansökan NetworkingIsFun, ange en företagsidentifierare, ställ in "iPhone" för enhetsfamiljen och avmarkera "Använd storyboards". Du kan lämna resten orört, men se till att Använd automatisk referensräkning är kontrollerad. Berätta Xcode där du vill spara ditt projekt och klicka på "Spara".


Lägga till tabell- och aktivitetsindikatorvyer

Även om gränssnittsbyggaren är bra bygger jag ofta mina gränssnitt på ett programmatiskt sätt, och det är vad vi ska göra i den här handledningen. Det gör det möjligt för oss att bara fokusera på koden utan att distraheras av Interface Builder. Öppna ViewController.h och skapa tre instansvariabler (ivars) samt egenskaper för dessa ivars. Eftersom vi ska arbeta med en tabellvy, glöm inte att göra din bildskärmskontroll överensstämmer med UITableViewDataSource och UITableViewDelegate protokoll. Din bildkontrollans huvudfil ska nu likna den som visas nedan:

 #importera  @interface ViewController: UIViewController  UITableView * _tableView; UIActivityIndicatorView * _activityIndicatorView; NSArray * _movies;  @property (nonatomic, behåll) UITableView * tableView; @property (nonatomic, behåll) UIActivityIndicatorView * activityIndicatorView; @property (nonatomic, behåll) NSArray * filmer; @slutet

Om du är förvirrad av att använda underskrifter rekommenderar jag att du läser om det här. Ta bort underskrifterna om du tycker att det ser gult ut eller gör dig obekväm. Bortsett från underskrifterna borde det inte finnas några överraskningar. Vi förklarar vår UITableView och UIActivityIndicatorView samt en NSArray, som vi ska använda för att lagra resultaten som vi kommer tillbaka från vår sökfråga. Redo? Låt oss gå över till vår bildskärmshanterings implementeringsfil.

Eftersom vi förklarade tre egenskaper i vår headerfil måste vi syntetisera sina accessors i ViewController.m. Återigen, om underskrifterna förvirrar dig, kan du lämna dem.

 @synthesize tableView = _tableView, activityIndicatorView = _aktivitetIndicatorView, movies = _movies;

I vår viewDidLoad metod, vi ställer in våra tabell- och aktivitetsindikatorvyer. Koden nedan borde vara självklarande för det mesta. Om du aldrig har skapat en tabellvy utan att använda gränssnittsbyggare, kanske du ser några rader som inte är kända för dig. Istället för att leda bordet upp i Interface Builder tar vi hand om det här i viewDidLoad metod. Efter att ha ringt superklassen " viewDidLoad metod initierar vi vår tabellvy med en ram och en stil, och vi ställer in vår synhållare som datakälla och delegerar i vår tabellvy. När vår applikation lanseras döljer vi vår tabellvy eftersom vi inte har något att visa så länge som vår fråga inte har returnerat några resultat. Innan vi lägger till tabellvyn som en undervy till vår visningskontrollörs vy, ställer vi in ​​sin autorescerande mask. Den autorescerande masken definierar hur tabellvyn ska ändras om föräldravyn - visningscontrollerens vy som vi lägger till i tabellvisningen - ändras i storlek. Detta händer när enheten roteras, till exempel. Förvirrad? Oroa dig inte om det. Det är inte viktigt för den här applikationen.

 - (void) viewDidLoad [super viewDidLoad]; // Inställning av 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 = self; self.tableView.delegate = self; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.tableView.hidden = YES; [self.view addSubview: self.tableView]; // Inställning Aktivitetsindikator Visa 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 datakälla self.movies = [[NSArray alloc] init]; 

Att ställa in aktivitetsindikatorvyn är lika enkelt. Vi initierar aktivitetsindikatorvyn med en fördefinierad stil, ställa in dess hidesWhenStopped egendom till JA, och placera den i mitten av dess föräldravyn. Efter att du har lagt till den i vystyrningens vy börjar vi animera aktivitetsindikatorn. Aktivitetsindikatorn kommer automatiskt att visa sig eftersom vi har ställt in hidesWhenStopped egendom till JA.

I slutet av vår viewDidLoad metod, vi initierar bio array. Vi använder det senare för att lagra resultaten av vår sökfråga.


Tabellprotokoll

För denna handledning kommer vi bara att implementera två metoder för protokollet för tabellvisning av datakälla. Båda dessa metoder är nödvändiga. Det här är den minsta implementeringen som krävs för att få vår tabellvisning på gång. Trots att vi har ställt vår vyskontroller som tabellvyns delegat använder vi inte någon av delegatormetoderna i vår ansökan. Om du har använt en tabellvy tidigare kommer du inte hitta några överraskningar i de metodreduktioner som visas nedan.

 - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) avsnitt if (self.movies && self.movies.count) return self.movies.count;  annars return 0;  - (UITableViewCell *) tableView: (UITableView *) tableVisa cellForRowAtIndexPath: (NSIndexPath *) indexPath static NSString * cellID = @ "Cell Identifier"; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: cellID]; om (! cell) cell = [[UITableViewCell-allokering] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: cellID];  returcell; 

I Tableview: numberOfRowsInSection:, Vi måste returnera antalet rader i varje avsnitt i tabellvyn. I vårt exempel innehåller tabellvyn bara ett avsnitt (standard), vilket gör allt lite lättare. Först kontrollerar vi om vår bio variabeln är inte noll och vi verifierar att den innehåller objekt. Om båda dessa krav är uppfyllda returnerar vi antalet artiklar i filmmatrisen, om inte, returnerar vi noll.

Vår Tableview: cellForRowAtIndexPath: Metoden är också grundläggande. Vi börjar med att fråga vår tabellvy om det finns en cell som vi kan återanvända. Om så inte är fallet skapar vi en ny cell med en stil och återanvändningsidentifierare. Vi avslutar vår implementering genom att returnera vår cell. Detta kommer att göra för nu. Du kan nu bygga och köra din ansökan. Om du följde stegen på rätt sätt borde du se aktivitetsindikatorn som snurrar som galen och tabellvisningen ska döljas.


Lägga till AFNetworking i mixen

Att lägga AFNetworking till ditt projekt är lätt som paj. Börja med att ladda ner biblioteket från GitHub och hämta arkivet. Arkivet innehåller en mapp som heter AFNetworking, som innehåller de källfiler vi behöver inkludera i vårt projekt. Dra hela den här mappen till ditt Xcode-projekt och se till att du kontrollerar Kopiera objekt till destinationsgruppens mapp (om det behövs) och lägg till källfilerna till ditt mål också.

Efter att ha lagt till AFNetworking-biblioteket till ditt projekt, bygga och springa din ansökan och titta på när allt faller ifrån varandra. Vad hände med vårt projekt? Varför får vi alla dessa varningar och fel? När vi inrättade vårt Xcode-projekt aktiverade vi Automatisk referensräkning (ARC). Vid skrivningstillfället använder AFNetworking-biblioteket inte ARC. Oroa dig inte, men vi kan fortfarande använda detta snygga bibliotek med mycket liten ansträngning. Allt vi behöver göra är att berätta för kompilatorn att alla källfiler i AFNetworking-biblioteket inte använder ARC. Det är allt.

Hur gör vi det här? Välj ditt projekt i Project Navigator och välj ditt mål. Klicka på Bygga faser fliken i den övre navigeringen och öppna Kompilera källor låda. I denna tabell visas alla källfiler kompilatorn kommer att kompilera vid kompileringstid. Den vänstra kolumnen visar namnen på filerna och den högra kolumnen visar vilka flaggor kompilatorn ska veta om.

Du kan se dessa flaggor som instruktioner eller meddelanden för kompilatorn. Allt du behöver göra är att lägga till en kompilatorflagga för varje källfil i AFNetworking-biblioteket. För att göra detta, välj en källfil från listan och dubbelklicka på cellen i den högra kolumnen. Ett litet fönster visas där du kan lägga till en eller flera kompilatorflaggor. I vårt fall, skriv bara -FNO-objc-arc och klicka Gjort. Den här flaggan berättar kompilatorn om att källfilen inte använder ARC. Se till att du lägger till den här flaggan i alla tio källfilerna i AFNetworking-biblioteket.


Fråga iTunes Store Search API

AFNetworking är ett bibliotek som kan göra mycket för dig, men idag kommer vi bara att använda två snygga funktioner. Innan vi kan börja använda AFNetworking-klasserna måste vi lägga till följande importdeklaration strax under den första importdeklarationen i din visningskontrollans implementeringsfil.

 #import "AFNetworking.h"

Denna importdeklaration ger oss tillgång till alla AFNetworking-klasserna. Gå tillbaka till vår vyskontroller viewDidLoad metod och lägg till följande snipp direkt efter initialiseringen av bio array.

 NSURL * url = [[NSURL tilldela] initWithString: @ "http://itunes.apple.com/search?term=harry&country=us&entity=movie"); NSURLRequest * request = [[NSURLRequest alloc] initWithURL: url]; AFJSONRequestOperation * operation = [AFJSONRequestOperation JSONRequestOperationWithRequest: begär framgång: ^ (NSURLRequest * request, NSHTTPURLResponse * svar, id JSON) NSLog (@ "% @", JSON);  fel: ^ (NSURLRequest * request, NSHTTPURLResponse * svar, NSError * fel, id JSON) NSLog (@ "Förfrågan misslyckades med fel:% @,% @", fel, error.userInfo); ]; [driftsstart];

Låt mig förklara vad som händer. I första raden skapar vi NSURL för vår begäran. Strängen som vi använder vid initialiseringen överensstämmer med det format som iTunes Store Search API förväntar sig. Synkroniseringen i Search API är ganska okomplicerad: Termen vi söker är "harry", vi begränsar vår sökning till den amerikanska iTunes Store, och vi letar bara efter filmer. Lätt, höger?

Därefter initierar vi en NSURLRequest och skickar in NSURL som vi just skapat. Sedan AFNetworking sparkar in. AFNetworking innehåller några mycket specialiserade klasser som gör vårt jobb väldigt enkelt. Den vi använder här är AFJSONRequestOperation. Det här är en klass som är utformad för att hämta och analysera JSON-data i bakgrunden. Som namnet antyder är denna klass en underklass av NSOperation eller för att vara mer exakt, en av superklasserna i denna klass ärver från NSOperation. Klassen låter dig hämta de begärda uppgifterna och det analyserar även JSON-svaret. Det betyder att vi inte behöver hantera rå JSON. De data som den returnerar är redo att användas i din ansökan. AFNetworking använder den inbyggda JSON-parsern på iOS 5 och faller tillbaka till sin egen JSON-parser för äldre iOS-versioner.

Att använda AFJSONRequestOperation är lätt eftersom det bara har en klassmetod. Denna klassmetod accepterar tre argument: (1) en NSURLRequest, (2) ett framgångsblock, exekverat när förfrågan lyckas, och (3) ett felblock, som utförs när begäran försvinner. Om block är nya för dig eller om du inte är bekväm med att använda dem, rekommenderar jag att du läser handledning av Collin Ruffenach om block och uppräkning på Mobiletuts +. Succesblocket tar tre argument: (1) vår NSURLRequest, (2) NSHTTPURLResponse av vår begäran, och (3) ett analyserat JSON-objekt. Felsteget är nästan identiskt. Den enda skillnaden är att det tar ett ytterligare argument, en NSError som innehåller mer information om vad som gick fel om vår begäran misslyckades.

För testning loggar vi det analyserade JSON-objektet för att se vad iTunes Store Search API skickar tillbaka till oss. Dessutom loggar vi också felet i felblocket om vår begäran råkar misslyckas. Innan vi bygger upp och kör vår ansökan igen måste vi starta operationen genom att ringa Start på vårt operationsobjekt. Bygg och kör din applikation och kolla på utgången i konsolen.

Om allt gick bra ser du resultatet av vår begäran som är inloggad i konsolen. Det analyserade JSON-objektet är en ordbok med två nycklar: (1) resultCount, vilket innehåller antalet återkomna resultat och (2) det faktiska resultat som en rad ordböcker. Vi loggade inte bara svaret på konsolen för att se om vår begäran lyckades, vi kan nu se nycklarna för varje objekt i resultatmatrisen. Vi behöver dessa nycklar för att visa viss information i vår tabellvy.


Följer tabellvyn

Vi är nu redo att visa resultaten i vår tabellvy. Ersätt loggutlåtelsen i succéblocket med biten som visas nedan. Vi börjar med att tilldela resultatraden för responsobjektet till filmmatrisen. Det enda som kvarstår är att dölja aktivitetsindikatorn genom att stoppa den, visa tabellvyn och ladda upp tabellvyn med de nya data som lagras i filmrutan.

 self.movies = [JSON objectForKey: @ "results"]; [self.activityIndicatorView stopAnimating]; [self.tableView setHidden: NO]; [self.tableView reloadData];

Nästa ändrar vi Tableview: cellForRowAtIndexPath: metod. Justera ditt genomförande för att återspegla det nedan. Efter att ha fått en referens till en cell, frågar vi filmmatrisen för det rätta objektet och uppdaterar etiketterna i cellen med filmens titel och regissör. Bygg och kör din ansökan.

 - (UITableViewCell *) tableView: (UITableView *) tableVisa cellForRowAtIndexPath: (NSIndexPath *) indexPath static NSString * cellID = @ "Cell Identifier"; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: cellID]; om (! cell) cell = [[UITableViewCell-allokering] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: cellID];  NSDictionary * movie = [self.movies objectAtIndex: indexPath.row]; cell.textLabel.text = [movie objectForKey: @ "trackName"]; cell.detailTextLabel.text = [filmobjektForKey: @ "artistName"]; returcell; 

Du kanske har märkt att det inte finns några miniatyrer att se. Låt oss fixa det genom att lägga till tre extra linjer till vår Tableview: cellForRowAtIndexPath: metod. Bygg och kör din ansökan.

 NSURL * url = [[NSURL tilldela] initWithString: [movie objectForKey: @ "artworkUrl100"]]; NSData * data = [NSData dataWithContentsOfURL: url]; cell.imageView.image = [[UIImage tilldela] initWithData: data];

Visste du att vår tabellvy inte rullar smidigt. Varför är det så? Som jag nämnde i en tidigare handledning måste du alltid se till att huvudtråden i din ansökan är mottaglig. I den nuvarande implementeringen av vår Tableview: cellForRowAtIndexPath: Metod, vi laddar ner miniatyrerna på huvudtråden. Det betyder att användargränssnittet inte kan uppdateras förrän en begäran om miniatyrbild är klar. Våra miniatyrer är små så förfrågningarna tar inte för lång tid att slutföra, men tänk på att vi tar samma sätt för större tillgångar. Användarupplevelsen skulle vara hemskt. Även för vår enkla applikation är användarupplevelsen oacceptabel. Vi kan dock åtgärda detta med en mycket användbar funktion i AFNetworking-biblioteket.


AFNetworking till räddningen

Skaparna av AFNetworking såg också behovet av att ladda ner tillgångar i bakgrunden. De skapade därför en kategori för UIImageView. Den här kategorin låter dig ladda ner bilder i bakgrunden med endast två rader kod. Denna kategori är en sann livsuppehållare. Ta en titt på biten nedan.

 NSURL * url = [[NSURL tilldela] initWithString: [movie objectForKey: @ "artworkUrl100"]]; [cell.imageView setImageWithURL: url placeholderImage: [UIImage imageNamed: @ "placeholder"]];

Den första raden av kod förblir densamma. I den andra raden berättar vi på bildvyn där miniatyrbilden ligger genom att skicka en NSURL och vi skickar in en platshållarbild, som visas så länge som vår begäran inte har returnerats. Hur coolt är inte det? Allt vi behöver göra är att lägga till en platshållare bild till vårt projekt. Det här kan vara vilken bild du vill, men du hittar den bild som jag har använt som platshållare i hämtningsfilen som bifogas denna handledning. När du har lagt till platsinnehållsbilden, bygg och kör din applikation och testa själv hur smidig tabellvyn rullar!


Slutsats

Observera att vår applikation är väldigt grundläggande vid utförandet eftersom det inte gör någon cache och vi kan bara söka i iTunes Store för termen "harry" i filmavsnittet. Men med mycket liten ansträngning kan du göra en snygg applikation för att söka i iTunes Store på ett mer dynamiskt sätt.

Jag hoppas att denna handledning har övertygat dig om att AFNetworking-biblioteket är ett utmärkt verktyg för att få i din arsenal. Det kan göra mycket mer än vad jag visade dig i det här inlägget, men huvudmålet med denna handledning är att få dig igång med AFNetworking och redo att använda den i en verklig scenarie.