før iOS 7 var udviklere ret begrænsede i, hvad de kunne gøre, da deres apps forlod forgrunden. Bortset fra VOIP og placeringsbaserede funktioner var den eneste måde at udføre kode i baggrunden på at bruge baggrundsopgaver, begrænset til at køre i et par minutter. Hvis du vil hente en stor video til offline visning eller sikkerhedskopiere en brugers fotos til din server, kan du kun fuldføre en del af arbejdet.
iOS 7 tilføjer to nye API ‘ er til opdatering af din apps brugergrænseflade og indhold i baggrunden. Den første, baggrund hente, giver dig mulighed for at hente nyt indhold fra netværket med jævne mellemrum. Den anden, Fjernunderretninger, er en ny funktion, der udnytter Push-meddelelser til at underrette en app, når en begivenhed har fundet sted. Begge disse nye mekanismer hjælper dig med at holde din apps interface opdateret og kan planlægge arbejdet med den nye Background Transfer-tjeneste, som giver dig mulighed for at udføre netværksoverførsler uden for processen (overførsler og uploads).
baggrund Hent og Fjernunderretninger er enkle applikation delegeret kroge med 30 sekunders vægur tid til at udføre arbejde, før din app er suspenderet. De er ikke beregnet til CPU-intensivt arbejde eller langvarige opgaver, snarere er de til at stå i kø med langvarige netværksanmodninger, som en stor filmoverførsel eller udføre hurtige indholdsopdateringer.
fra en brugers perspektiv er den eneste åbenlyse ændring til multitasking den nye appskifter, der viser et øjebliksbillede af hver apps brugergrænseflade, som det var, da det forlod forgrunden. Men der er en grund til at vise snapshots – du kan nu opdatere din apps snapshot, når du har gennemført baggrundsarbejde, og viser en forhåndsvisning af nyt indhold. Sociale netværk, nyheder eller vejr-apps kan nu vise det nyeste indhold, uden at brugeren behøver at åbne appen. Vi får se, hvordan du opdaterer snapshot senere.
baggrund hentning
baggrund hentning er en slags smart polling mekanisme, der fungerer bedst for apps, der har hyppige indhold opdateringer, ligesom sociale netværk, nyheder, eller vejr apps. Systemet vækker appen baseret på en brugers adfærd og sigter mod at udløse baggrundshentninger inden brugeren starter appen. For eksempel, hvis brugeren altid bruger en app på 1 pm, systemet lærer og tilpasser, udfører henter forud for brug perioder. Baggrundshentninger samles på tværs af apps af enhedens radio for at reducere batteriforbruget, og hvis du rapporterer, at nye data ikke var tilgængelige under en hentning, kan iOS tilpasse sig ved hjælp af disse oplysninger for at undgå hentninger i stille tider.
det første skridt i at aktivere baggrund Hent er at angive, at du vil bruge funktionen i UIBackgroundModes
nøgle i din info plist. Den nemmeste måde at gøre dette på er at bruge fanen Nye funktioner i project editor, som indeholder en Baggrundstilstande sektion for nem konfiguration af multitasking muligheder.
Alternativt kan du redigere nøglen manuelt:
<key>UIBackgroundModes</key><array> <string>fetch</string></array>
næste, fortæl iOS, hvor ofte du gerne vil hente:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ ; return YES;}
standard henteintervallet er aldrig, så du bliver nødt til at indstille et tidsinterval, ellers bliver appen aldrig kaldt i baggrunden. Værdien af UIApplicationBackgroundFetchIntervalMinimum
beder systemet om at styre, når din app er vågnet, så ofte som muligt, men du skal angive dit eget tidsinterval, hvis dette er unødvendigt. For eksempel kan en vejr-app muligvis kun opdatere forholdene hver time. iOS venter mindst det angivne tidsinterval mellem baggrundshentninger.
hvis din applikation tillader en bruger at logge ud, og du ved, at der ikke vil være nye data, kan du indstille minimumBackgroundFetchInterval
tilbage til UIApplicationBackgroundFetchIntervalNever
for at være en god borger og for at spare ressourcer.
det sidste trin er at implementere følgende metode i din ansøgningsdelegat:
- (void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSURLSessionConfiguration *sessionConfiguration = ; NSURLSession *session = ; NSURL *url = initWithString:@"http://yourserver.com/data.json"]; NSURLSessionDataTask *task = ; // Start the task ;}
det er her, du kan udføre arbejde, når du er vågnet af systemet. Husk, at du kun har 30 sekunder til at afgøre, om nyt indhold er tilgængeligt, til at behandle det nye indhold og til at opdatere din brugergrænseflade. Dette skal være tid nok til at hente data fra netværket og hente et par miniaturebilleder til din brugergrænseflade, men ikke meget mere. Når dine netværksanmodninger er afsluttet, og din brugergrænseflade er blevet opdateret, skal du ringe til færdiggørelseshandleren.
færdiggørelseshandleren tjener to formål. Først måler systemet den strøm, der bruges af din proces, og registrerer, om nye data var tilgængelige baseret på argumentet UIBackgroundFetchResult
, du bestod. For det andet, når du ringer til færdiggørelseshandleren, tages et øjebliksbillede af din brugergrænseflade, og appskifteren opdateres. Brugeren vil se det nye indhold, når han eller hun skifter apps. Denne færdiggørelseshåndterings snapshottingadfærd er fælles for alle færdiggørelseshåndterere i de nye multitasking API ‘ er.
i en applikation i den virkelige verden skal du overføre completionHandler
Til underkomponenterne i din applikation og kalde den, når du har behandlet data og opdateret din brugergrænseflade.
på dette tidspunkt undrer du dig måske over, hvordan iOS kan snapshot din apps brugergrænseflade, når den kører i baggrunden, og hvordan applikationens livscyklus fungerer med baggrund hentning. Hvis din app i øjeblikket er suspenderet, vil systemet vække den, før du ringer application: performFetchWithCompletionHandler:
. Hvis din app ikke kører, starter systemet den og kalder de sædvanlige delegerede metoder, herunder application: didFinishLaunchingWithOptions:
. Du kan tænke på det som den app kører nøjagtig samme måde, som hvis brugeren havde lanceret det fra Springboard, undtagen UI er usynlig, gengivet offscreen.
i de fleste tilfælde udfører du det samme arbejde, når applikationen starter i baggrunden, som du ville gøre i forgrunden, men du kan registrere baggrundslanceringer ved at se på egenskaben applicationState
for UIApplication:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ NSLog(@"Launched in background %d", UIApplicationStateBackground == application.applicationState); return YES;}
Testing baggrund hente
der er to måder, du kan simulere en baggrund hente. Den nemmeste metode er at køre din applikation fra kode og klikke simulere baggrund Hent under kode Debug menu, mens din app kører.
Alternativt kan du bruge et skema til at ændre, hvordan din app kører. Vælg Skema under menupunktet kode produkt, og administrer derefter ordninger. Herfra skal du redigere eller tilføje et nyt skema og markere afkrydsningsfeltet Start på grund af en baggrund Hent begivenhed som vist nedenfor.
Fjernunderretninger
Fjernunderretninger giver dig mulighed for at underrette din app, når vigtige begivenheder opstår. Du kan have nye chatbeskeder til at levere, bryde nyheder advarsler til at sende, eller den seneste episode af din brugers foretrukne TV-program klar til ham eller hende til at hente til offline visning. Fjernunderretninger er gode til sporadisk, men umiddelbart vigtigt indhold, hvor forsinkelsen mellem baggrundshentninger muligvis ikke er acceptabel. Fjernunderretninger kan også være meget mere effektive end Baggrundsindhentning, da din applikation kun lanceres, når det er nødvendigt.
en Fjernmeddelelse er egentlig bare en normal Push-meddelelse med content-available
flagsættet. Du kan sende et skub med en advarselsmeddelelse, der informerer brugeren om, at der er sket noget, mens du opdaterer brugergrænsefladen i baggrunden. Men Fjernunderretninger kan også være tavse, der ikke indeholder nogen advarselsmeddelelse eller lyd, der kun bruges til at opdatere din apps interface eller udløse baggrundsarbejde. Du kan derefter sende en lokal meddelelse, når du er færdig med at hente eller behandle det nye indhold.
Silent push notifikationer er Sats-begrænset, så vær ikke bange for at sende så mange som din ansøgning behov. iOS og APNS-serverne styrer, hvor ofte de leveres, og du får ikke problemer med at sende for mange. Hvis dine push-underretninger er spredt, kan de blive forsinket, indtil næste gang enheden sender en keep-alive-pakke eller modtager en anden underretning.
afsendelse af Fjernmeddelelser
hvis du vil sende en fjernmeddelelse, skal du indstille det tilgængelige flag for indhold i en push-meddelelses nyttelast. Det tilgængelige flag er den samme nøgle, der bruges til at underrette aviskiosk-apps, så de fleste push-scripts og biblioteker understøtter allerede fjernunderretninger. Når du sender en Fjernmeddelelse, kan du også medtage nogle data i meddelelsesbelastningen, så din applikation kan henvise til begivenheden. Dette kan spare dig for et par netværksanmodninger og øge din apps lydhørhed.
jeg anbefaler at bruge Nomad CLI ‘ s Houston-værktøj til at sende push-beskeder, mens du udvikler, men du kan bruge dit yndlingsbibliotek eller script.
du kan installere Houston som en del af nomad-CLI ruby gem:
gem install nomad-cli
og send derefter en meddelelse med apn-værktøjet inkluderet i Nomad
# Send a Push Notification to your Deviceapn push <device token> -c /path/to/key-cert.pem -n -d content-id=42
her angiver -n
– flaget, at den tilgængelige nøgle til indhold skal inkluderes, og -d
giver os mulighed for at tilføje vores egne datanøgler til nyttelasten.
den resulterende anmeldelse nyttelast ser sådan ud:
{ "aps" : { "content-available" : 1 }, "content-id" : 42}
iOS 7 tilføjer en ny applikationsdelegeringsmetode, der kaldes, når der modtages en push-meddelelse med den tilgængelige nøgle til indhold:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSLog(@"Remote Notification userInfo is %@", userInfo); NSNumber *contentID = userInfo; // Do something with the content ID completionHandler(UIBackgroundFetchResultNewData);}
igen lanceres appen i baggrunden og får 30 sekunder til at hente nyt indhold og opdatere dets brugergrænseflade, før du ringer til færdiggørelseshandleren. Vi kunne udføre en hurtig netværksanmodning, som vi gjorde i eksemplet med hentning af baggrund, men lad os bruge den kraftfulde nye Baggrundsoverførselstjeneste til at spørge om en stor overførselsopgave og se, hvordan vi kan opdatere vores brugergrænseflade, når den er afsluttet.
Nsurlsession and Background Transfer Service
mens NSURLSession
er en ny klasse i iOS 7, henviser den også til den nye teknologi inden for Fundamentnetværk. Beregnet til at erstatte NSURLConnection
bevares velkendte begreber og klasser som NSURL
, NSURLRequest
og NSURLResponse
. Du arbejder med NSURLConnection
‘s udskiftning, NSURLSessionTask
, for at fremsætte netværksanmodninger og håndtere deres svar. Der er tre typer sessionsopgaver – data, Hent og upload – som hver tilføjer syntaktisk sukker til NSURLSessionTask
, så du skal bruge den passende til din brugssag.
en NSURLSession
koordinerer en eller flere af disse NSURLSessionTask
s og opfører sig i henhold til NSURLSessionConfiguration
, som den blev oprettet med. Du kan oprette flere NSURLSession
s for at gruppere relaterede opgaver med samme konfiguration. For at interagere med Baggrundsoverførselstjenesten opretter du en sessionskonfiguration ved hjælp af . Opgaver, der føjes til en baggrundssession, køres i en ekstern proces og fortsætter, selvom din app er suspenderet, går ned eller dræbes.
NSURLSessionConfiguration
giver dig mulighed for at indstille standard HTTP-overskrifter, konfigurere cache-politikker, begrænse brugen af mobilnetværk og mere. En mulighed er discretionary
flag, som gør det muligt for systemet at planlægge opgaver for optimal ydeevne. Hvad dette betyder er, at dine overførsler kun går over trådløst internet, når enheden har tilstrækkelig strøm. Hvis batteriet er lavt, eller kun en mobilforbindelse er tilgængelig, kører din opgave ikke. Flagget discretionary
har kun en effekt, hvis sessionskonfigurationsobjektet er konstrueret ved at kalde metoden backgroundSessionConfiguration:
, og hvis baggrundsoverførslen startes, mens din app er i forgrunden. Hvis overførslen startes fra baggrunden, vil overførslen altid køre i skønsmæssig tilstand.
nu ved vi lidt om NSURLSession
, og hvordan en baggrundssession fungerer, lad os vende tilbage til vores eksempel på Fjernmeddelelse og tilføje noget kode for at spørge om en overførsel på baggrundsoverførselstjenesten. Når overførslen er færdig, giver vi brugeren besked om, at filen er tilgængelig til brug.
Nsurlsessionnloadtask
lad os først og fremmest håndtere en Fjernmeddelelse og spørge en NSURLSessionDownloadTask
om baggrundsoverførselstjenesten. I backgroundURLSession
opretter vi en NURLSession
med en baggrundssessionskonfiguration og tilføjer vores applikationsdelegat som sessiondelegat. Dokumentationen fraråder instantiering af flere sessioner med samme identifikator, så vi bruger dispatch_once
for at undgå potentielle problemer:
- (NSURLSession *)backgroundURLSession{ static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSString *identifier = @"io.objc.backgroundTransferExample"; NSURLSessionConfiguration* sessionConfig = ; session = ]; }); return session;}- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSLog(@"Received remote notification with userInfo %@", userInfo); NSNumber *contentID = userInfo; NSString *downloadURLString = ]; NSURL* downloadURL = ; NSURLRequest *request = ; NSURLSessionDownloadTask *task = downloadTaskWithRequest:request]; task.taskDescription = ]; ; completionHandler(UIBackgroundFetchResultNewData);}
vi opretter en overførselsopgave ved hjælp af klassemetoden NSURLSession
og konfigurerer dens anmodning og giver en beskrivelse til brug senere. Du skal huske at ringe for faktisk at starte opgaven, da alle sessionsopgaver begynder i suspenderet tilstand.
nu skal vi implementere NSURLSessionDownloadDelegate
metoderne til at modtage tilbagekald, når overførslen er afsluttet. Det kan også være nødvendigt at implementere NSURLSessionDelegate
eller NSURLSessionTaskDelegate
metoder, hvis du har brug for at håndtere godkendelse eller andre begivenheder i sessionens livscyklus. Du bør konsultere Apples dokumentlivscyklus for en URL-Session med brugerdefinerede delegerede, hvilket forklarer den fulde livscyklus på tværs af alle typer sessionsopgaver.
ingen af NSURLSessionDownloadDelegate
delegerede metoder er valgfri, selvom den eneste, hvor vi skal handle i dette eksempel, er . Når opgaven er færdig med at hente, får du en midlertidig URL til filen på disken. Du skal flytte eller kopiere filen til din apps lagerplads, da den fjernes fra midlertidig lagring, når du vender tilbage fra denne delegerede metode.
#Pragma Mark - NSURLSessionDownloadDelegate- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ NSLog(@"downloadTask:%@ didFinishDownloadingToURL:%@", downloadTask.taskDescription, location); // Copy file to your app's storage with NSFileManager // ... // Notify your UI}- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{}- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{}
hvis din app stadig kører i forgrunden, når opgaven med baggrundssessionen er afsluttet, er ovenstående kode tilstrækkelig. I de fleste tilfælde kører din app dog ikke, eller den suspenderes i baggrunden. I disse tilfælde skal du implementere to application delegates-metoder, så systemet kan vække din ansøgning. I modsætning til tidligere tilbagekald af delegerede kaldes programdelegatet to gange, da dine session-og opgavedeltagere muligvis modtager flere meddelelser. App delegeret metode application: handleEventsForBackgroundURLSession:
kaldes før disse NSURLSession
delegeret meddelelser sendes, og URLSessionDidFinishEventsForBackgroundURLSession
kaldes bagefter. I den tidligere metode gemmer du en baggrund completionHandler
, og i sidstnævnte kalder du det for at opdatere din brugergrænseflade:
- (void) application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{ // You must re-establish a reference to the background session, // or NSURLSessionDownloadDelegate and NSURLSessionDelegate methods will not be called // as no delegate is attached to the session. See backgroundURLSession above. NSURLSession *backgroundSession = ; NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession); // Store the completion handler to update your UI after processing session events ;}- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{ NSLog(@"Background URL session %@ finished events.\n", session); if (session.configuration.identifier) { // Call the handler we stored in -application:handleEventsForBackgroundURLSession: ; }}- (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier{ if () { NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen.\n"); } ;}- (void)callCompletionHandlerForSession: (NSString *)identifier{ CompletionHandlerType handler = ; if (handler) { ; NSLog(@"Calling completion handler for session %@", identifier); handler(); }}
denne to-trins proces er nødvendig for at opdatere din app-brugergrænseflade, hvis du ikke allerede er i forgrunden, når baggrundsoverførslen er afsluttet. Derudover, hvis appen slet ikke kører, når baggrundsoverførslen er færdig, starter iOS den i baggrunden, og de foregående applikations-og sessionsdelegeringsmetoder kaldes efter application:didFinishLaunchingWithOptions:
.
konfiguration og begrænsning
vi har kort berørt kraften i baggrundsoverførsler, men du bør undersøge dokumentationen og se på de NSURLSessionConfiguration
muligheder, der bedst understøtter din brugssag. For eksempel NSURLSessionTasks
support ressource timeouts gennem NSURLSessionConfiguration
‘s timeoutIntervalForResource
ejendom. Du kan bruge dette til at angive, hvor længe du vil tillade, at en overførsel skal gennemføres, før du giver op helt. Du kan bruge dette, hvis dit indhold kun er tilgængeligt i en begrænset periode, eller hvis manglende overførsel eller upload af ressourcen inden for den givne timeInterval indikerer, at brugeren ikke har tilstrækkelig trådløs båndbredde.
ud over at hente opgaver, NSURLSession
Fuldt understøtter upload opgaver, så du kan uploade en video til din server i baggrunden og forsikre din bruger, at han eller hun ikke længere behøver at forlade app kører, som kunne have været gjort i iOS 6. Et godt strejf ville være at indstille sessionSendsLaunchEvents
egenskaben for din NSURLSessionConfiguration
til NO
, hvis din app ikke behøver at starte i baggrunden, når overførslen er afsluttet. Effektiv brug af systemressourcer holder både iOS og brugeren glad.
endelig er der et par begrænsninger i at bruge baggrundssessioner. Da en delegeret er påkrævet, kan du ikke bruge de enkle blokbaserede tilbagekaldsmetoder på NSURLSession
. Det er relativt dyrt at starte din app i baggrunden, så HTTP-omdirigeringer tages altid. Tjenesten baggrundsoverførsel understøtter kun HTTP og HTTPS, og du kan ikke bruge brugerdefinerede protokoller. Systemet optimerer overførsler baseret på tilgængelige ressourcer, og du kan ikke tvinge din overførsel til fremskridt i baggrunden på alle tidspunkter.
Bemærk også, at NSURLSessionDataTasks
slet ikke understøttes i baggrundssessioner, og du bør kun bruge disse opgaver til kortvarige, små anmodninger, ikke til overførsler eller uploads.
Resume
de kraftfulde nye multitasking-og netværks-API ‘ er i iOS 7 åbner en lang række muligheder for både nye og eksisterende apps. Overvej brugssagerne i din app, som kan drage fordel af out-of-process netværksoverførsler og friske data, og få mest muligt ud af disse fantastiske nye API ‘ er. Generelt skal du implementere baggrundsoverførsler, som om din applikation kører i forgrunden, foretage passende UI-opdateringer, og det meste af arbejdet er allerede gjort for dig.
-
Brug den relevante nye API til din apps indhold.
-
Vær effektiv, og ring færdiggørelseshåndterere så tidligt som muligt.
-
færdiggørelse handlere opdatere din app UI snapshot.
yderligere læsning
-
2013 session “Hvad er nyt med Multitasking”
-
2013 session “Hvad er nyt i Foundation netværk”
-
URL Loading System programmering Guide