NSURLConnection - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Seriály

Více seriálů



Software

NSURLConnection

11. dubna 2007, 00.00 | V jen trošku náročnějších aplikacích však není pro toto třída NSURL nejvhodnější, neboť nenabízí dostatečně flexibilní služby; daleko lepší je pro přístup k datům na internetu využít služeb třídy NSURLConnection – a na tu se právě podíváme dnes.

V minulém díle našeho seriálu o programování ve vývojovém prostředí Cocoa jsme se začali zabývat prací se sítí a přístupem k síťovým zdrojům. Ukázali jsme si třídu NSURL a její služby pro representaci internetových symbolických adres; seznámili jsme se také s tím, jak lze v jednoduchých případech využít přímo třídy NSURL i pro načítání obsahu ze sítě.

V jen trošku náročnějších aplikacích však není pro toto třída NSURL nejvhodnější, neboť nenabízí dostatečně flexibilní služby; daleko lepší je pro přístup k datům na internetu využít služeb třídy NSURLConnection – a na tu se právě podíváme dnes.

NSURLRequest

Nejprve ovšem na chvilku odbočíme a seznámíme se s pomocnou třídou NSURLRequest. Ta, jak její jméno ostatně naznačuje, representuje požadavek na přístup k nějakému URL; vlastní adresa, vyjádřená samozřejmě pomocí instance třídy NSURL, je pouze jednou, leč nikoli jedinou, součástí takového požadavku.

Nejjednodušší způsob, kterak vytvořit objekt třídy NSURLRequest, nepotřebuje nic jiného než právě URL – všechna ostatní pole se doplní standardními hodnotami:

NSURLRequest *request=[NSURLRequest requestWithURL:someURL];

V praxi však spíše využijeme druhý konstruktor requestWithURL:cachePolicy:timeoutInterval:, který nám umožní větší flexibilitu – jeho prostřednictvím můžeme určit timeout, po němž knihovny čekání na odpověď vzdáleného serveru vzdají a ohlásí chybu, a také požadovaný způsob využití lokální cache. Zde máme k dispozici následující hodnoty:

  • NSURLRequestUseProtocolCachePolicy: standardní využití cache, definované v rámci toho kterého protokolu;
  • NSURLRequestReloadIgnoringCacheData: data se vždy vyžádají od vzdáleného serveru; existuje-li záznam v cache, framework jej bude ignorovat;
  • NSURLRequestReturnCacheDataElseLoad: asi nejběžnější varianta: pokud jsou data k dispozici v cache paměti, použijí se; pouze v případě, že tomu tak není, vyžádá si je služba od vzdáleného serveru;
  • NSURLRequestReturnCacheDataDontLoad: režim "offline"; v tomto případě se k serveru nikdy nepřistupuje a data jsou načtena pouze z cache – nejsou-li zde k dispozici, ohlásí framewrok chybu (stejně jako kdyby byl např. server nepřístupný).

Výše uvedené služby ve většině případů zcela stačí; je však vhodné vědět, že knihovny Cocoa skutečně zkonstruují plnohodnotný HTTP request – pokud bychom ve výjimečném případě potřebovali přímý přístup k jeho konkrétním polím, třída NSURLRequest nám to také umožní.

Sestavení konekce

Jediné, co potřebujeme pro odeslání požadavku kromě instance třídy NSURLRequest, je "delegát" – objekt, který bude průběžně informován o tom, co se s připojením děje.

V jeho metodě si pak jen vyžádáme vytvoření instance třídy NSURLConnection se zadaným requestem a delegátem; nic jiného není zapotřebí a framework okamžitě zahájí přístup k serveru (a/nebo do cache, samozřejmě, v závislosti na zvolené hodnotě argumentu "cache policy" v requestu:

-(void)downloadContentsOfURL:(NSURL*)url {
  [NSURLConnection connectionWithRequest:
    [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestUseProtocolCachePolicy
      timeoutInterval:timeout]
    delegate:self];
}

Získání a zpracování výsledku

Je třeba si uvědomit, že třída NSURLConnection representuje skutečně právě připojení k serveru; ne již ale URL jako takové. Speciálně to znamená, že třída neobsahuje "stažená" data; k těm pouze nabídne svému delegátu přístup. Chceme-li tedy tato data získat, potřebujeme si pro ně připravit vhodné úložiště:

@interface OurDownloader:NSObject {
  NSMutableData *received;
}
@end

Jakmile instance třídy NSURLConnection spustí načítání dat, informuje svého delegáta o průběhu práce prostřednictvím standardních metod. Těch je řada (chceme-li, můžeme jejich prostřednictvím sledovat kupříkladu vlastní připojování k serveru a podobně); potřebné minimum však zahrnuje následující metody.

Prvou z nich framework zavolá kdykoli, když jsou prostřednictvím připojení přijata nějaká data. Vzhledem k tomu, že server může data poslat v několika částech (ačkoli to běžně nenastává), je vhodné s tím pro jistotu počítat:

-(void)connection:(NSURLConnection*)cc
       didReceiveData:(NSData*)dd {
    if (!data) data=[dd mutableCopy];
    else [data appendData:dd];
}

Druhá – a vlastně nejdůležitější – metoda delegáta je zavolána ve chvíli, kdy je "stahování" dat úspěšně dokončeno:

-(void)connectionDidFinishLoading:(NSURLConnection*)cc {
  NSLog(@"received %u bytes",[data count]);
  [self processData:data];
}

Chceme-li, můžeme samozřejmě data ihned po zpracování uvolnit; jak si ukážeme za chvilku, není to ale bezpodmínečně nutné, pokud nám nevadí, že náš objekt bude vždy udržovat data naposledy načtená.

Třetí metoda se zavolá namísto druhé v případě, kdy nelze operaci z nějakého důvodu dokončit; jejím argumentem samozřejmě je také instance třídy NSError, jež obsahuje informace o příčině problému:

-(void)connection:(NSURLConnection*)cc
       didFailWithError:(NSError*)error {
  NSLog(@"did not receive anything since: %@",error);
}

Podobně jako minule můžeme – nechceme-li udržovat neustále v objektu poslední data – obsah proměnné, data uvolnit; to proto, že je v principu např. možné to, že "spadlo" spojení k serveru poté, co již byla nějaká částečná data načtena.

Na první pohled se zdá, že toto zcela stačí; v praxi je však třeba implementovat ještě jednu metodu. Jde o to, že odpověď serveru může obsahovat také přesměrování na jiné URL; v takovém případě musíme "zahodit" dosud přijatá data a začít znovu. Nejvhodnější je na to metoda connection:didReceiveResponse:; odpovídající zprávu dostaneme vždy při přijetí odpovědi HTTP (tedy také hned poprvé – tím elegantně a bez další námahy zajistíme odstranění starých dat, i pokud je nebudeme uvolňovat v metodách connectionDidFinishLoading: a connection:didFailWithError:):

-(void)connection:(NSURLConnection*)cc
       didReceiveResponse:(NSURLResponse*)rr {
  [data release]; data=nil;
}

Zrušení požadavku

Poslední drobnost, jež se může hodit, je zpráva cancel – tu můžeme odeslat instanci třídy NSURLConnection (na niž si v tomto případě samozřejmě musíme udržovat explicitní odkaz) v případě, že chceme rozpracovaný požadavek explicitně zrušit. V takovém případě už od zrušené konekce nedostane delegát žádnou zprávu.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Tipy a Triky  

 » Rubriky  » Začínáme s  

 » Rubriky  » Software  

 

 

 

Nejčtenější články
Nejlépe hodnocené články
Apple kurzy

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: