iOS 7 SDK serviciu de transfer de fundal

Acest tutorial vă va arăta cum să utilizați serviciul de transfer de fundal, un API Multitasking oferit de iOS 7. Vă voi învăța cum să creați o aplicație care va descărca un fișier fără aplicația din prim-plan. Odată ce fișierul se descarcă complet, se va afișa un mesaj de notificare. Continuați să citiți pentru a crea acest serviciu!


Introducere

Serviciul de transfer de origine provenit de la versiunea iOS 6. Această caracteristică a permis aplicațiilor să transfere fișiere atât în ​​modul de prim plan, cât și în modul fundal, dar a limitat minutele. Cea mai mare problemă a fost atunci când "minutele limitate" nu au permis utilizatorului să descarce sau să încarce fișiere mari. Acesta este motivul pentru care Apple a îmbunătățit cadrul din iOS 7.

Cu iOS 7, această caracteristică a suferit modificări majore, printre care:

  • iOS gestionează descărcările și încărcările
  • Transferul continuă chiar și atunci când utilizatorul închide aplicația
  • Timpul este nelimitat
  • Poate fi pus în coadă oricând (fundal și fundal)
  • Aplicația se trezește pentru a gestiona autentificarea, erorile sau finalizarea
  • Aplicația include o vizualizare progresivă

Serviciul de transfer de fundal poate fi folosit pentru mai multe sarcini distincte și utile, cum ar fi: încărcarea fotografiilor sau videoclipurilor, combinarea preluării de fundal și a notificărilor la distanță și păstrarea actualizării aplicației, cum ar fi achizițiile pentru cărți, emisiuni TV, podcasturi, hărți și multe altele.


1. Configurați Proiectul

Pentru a crea acest serviciu, avem nevoie de o singură vizualizare cu următoarele proprietăți:

  • Un ViewController
  • Un NavigationController
  • Un element de bara (pentru a incepe downloadul)
  • Un UIDocumentInterationController (pentru a deschide descărcarea documentului PDF)

În primul rând, începeți un nou proiect iPhone Xcode. Apoi creați o Vizualizare individuală. Apoi, mergeți la Main.Storyboard și adăugați niște obiecte la noi Vedere. Pentru a adăuga NavigationController selectează Vizualizator standard al vizualizării. În meniul Xcode, selectați Editor> Încorporați în> Controller de navigare. Trebuie să trageți și să renunțați Articol de bara si Vizualizare progresivă la controlerul de vizualizare. Odată ce ați terminat, controlerul de vizualizare ar trebui să arate similar cu următoarea imagine:


Ilustrație a aplicației - după configurare - transfer de fundal

Acum, să adăugăm proprietățile necesare interacțiunii cu obiectele pe care le-am adăugat. În ViewController.h, adăugați următoarele rânduri:

 @property (slab, nonatomic) IBOutlet UIProgressView * progressView; - (IBAction) începe: (id) expeditor;

Acum modificați vizualizarea pentru ViewController.m. Va apărea un avertisment, dar nu vă îngrijorați; o vom rezolva mai târziu. Întoarceți-vă la Main.Storyboard și conectați obiectele cu proprietățile și acțiunile.

Acest pas este trivial, dar dacă aveți nelămuriri, puteți folosi secțiunea de comentarii de mai jos.


2. NSURLSession

NSURLSession clasa și clasele aferente oferă un API pentru descărcarea sau încărcarea conținutului prin HTTP. Acest API este responsabil pentru gestionarea unui set de sarcini de transfer. Va trebui să creați trei obiecte care se raportează direct la acea clasă: una NSURLSession, NSURLSessionDownloadTask, și UIDocumentInteractionController.

Ta ViewController.h va fi ceva de genul:

 @property (nonatomic) sesiune NSURLSession *; @property (nonatomic) NSURLSessionDownloadTask * downloadTask; @property (puternic, nonatomic) UIDocumentInteractionController * documentInteractionController;

În plus, veți declara și patru protocoale: NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate, și UIDocumentInteractionControllerDelegate. Ta @interface ar trebui să arate ca:

 @ interfață ViewController: UIViewController < NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate>

Proprietățile pe care le vom adăuga sunt utile pentru a instanțiza și manipula sesiunea noastră și procesul de descărcare, care vă va permite să reluați, suspendați, anulați sau să preluați starea. Ultima proprietate, UIDocumentInterationController este folosit pentru a prezenta documentul PDF descărcat în acest tutorial.

Acum treci la ViewController.m.

Prima sarcină de completat este adăugarea unui șir la locația fișierului pentru descărcare. Ar trebui să utilizați un standard PDF standard pentru Apple.

 static NSString * DownloadURLString = @ "https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf";

Pe viewDidLoad , permiteți instanțierii și setarea atât a vizualizărilor de sesiune, cât și a progresului:

 auto.session = [auto backgroundSession]; self.progressView.progress = 0; self.progressView.hidden = DA;

Deoarece apelați backgroundSession și nu există, trebuie să o declarați acum. Această metodă este responsabilă pentru expedierea unei acțiuni care va fi sesiunea de fundal. backgroundSession prin dispatch_once execută un bloc o singură dată pentru toată durata de viață a aplicației. NSString primit de către NSURLSessionConfiguration reprezintă ID-ul sesiunii noastre. Acest ID trebuie să fie unic pentru fiecare instanță NSURLSession.

Metoda completă este următoarea:

 - (NSURLSession *) backgroundSession static NSURLSession * sesiune = nil; static dispatch_once_t onceToken; dispatch_once (& onceToken, ^ NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfiguration: @ com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession]; session = [NSURLSession sessionWithConfiguration: delegate de configurare: self delegateQueue: nil]; sesiune de întoarcere; 

(IBAction) de pornire: (id) expeditor metoda începe descărcarea documentului. Apoi, veți iniția un proces NSURL și a NSURLRequest și utilizați downloadTask proprietate pentru a trece obiectul cererii la downloadTaskWithRequest metodă. Metoda completă este de mai jos.

 - (IBAction) începe: (id) expeditor if (self.downloadTask) return;  NSURL * downloadURL = [NSURL URLWithString: DownloadURLString]; NSURLRequest * request = [NSURLRequest requestWithURL: downloadURL]; auto.downloadTask = [auto.session downloadTaskWithRequest: cerere]; [auto.downloadTask resume]; self.progressView.hidden = NU; 

3. Protocoale

În acest moment, veți observa că sunt prezente trei avertismente. Ei declară că ar trebui implementată metoda protocolului. NSURLSessionDownloadDelegate protocol definește metodele de a gestiona sarcina de descărcare. Pentru a efectua descărcarea, este necesar să utilizați cele trei metode delegate.

Deci, adăugați următoarele trei metode:

  • 1. (int64_t) BytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite
  • 2. (void) URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL
  • 3. (void) Adresă URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes

(void) Adresă URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite metoda este responsabilă pentru urmărirea procesului de descărcare globală. De asemenea, actualizează progressView în consecinţă. Metoda completă este de mai jos.

 - (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite if (downloadTask == self.downloadTask) double progress = () () dublu) totalBytesWritten / (dublu) totalBytesExpectedToWrite; NSLog (@ "DownloadTask:% @ progress:% lf", downloadTask, progress); dispatch_async (dispatch_get_main_queue (), ^ auto.progressView.progress = progress;); 

4. Descărcați sarcina

(void) URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL metoda se ocupă de datele în sine (origine și destinație). Controlează fișierul numai după ce este descărcat complet. Pentru a spune pur și simplu, spune delegatului că o sarcină de descărcare a terminat descărcarea. Acesta conține sarcina de sesiune care sa terminat, sarcina de descărcare care sa terminat și o adresă URL a fișierului în care poate fi găsit fișierul temporar. Ar trebui să arate astfel:

 - (void) URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL NSFileManager * fileManager = [NSFileManager defaultManager]; NSArray * URL-uri = [fileManager URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask]; NSURL * documentsDirectory = [URL-uri objectAtIndex: 0]; NSURL * originalURL = [[DownloadTask originalRequest] URL]; NSURL * destinationURL = [documentDirectory URLByAppendingPathComponent: [originalURL lastPathComponent]]; NSError * errorCopy; // În scopul testării, eliminați orice fișier care apare la destinație. [fileManager removeItemAtURL: eroare destinațieURL: NULL]; BOOL succes = [fileManager copyItemAtURL: downloadURL toURL: eroare destinațieURL: & errorCopy]; dacă (succesul) dispatch_async (dispatch_get_main_queue (), ^ // descărcarea terminată - deschideți pdf self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL: destinationURL]; // Configurați controlerul de interacțiune a documentului [self.documentInteractionController setDelegate: self]; PDF [auto.documentInteractionController prezentPreviewAnimated: YES]; self.progressView.hidden = YES;);  altceva NSLog (@ "Eroare în timpul copierii:% @", [errorCopy localizedDescription]); 

În cele din urmă, (void) Adresă URLSession: (NSURLSession *) sesiune downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes trebuie, de asemenea, declarată. Dar fiți conștienți de faptul că nu o vom folosi mai departe.

 -(void) URLSession: (NSURLSession *) sesiunea downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes 

5. Sarcini de sesiune

Ați terminat aproape cu această clasă, rămân doar două metode: (void) URLSession: (NSURLSession *) sarcină sesiune: (NSURLSessionTask *) sarcină didCompleteWithError: (NSError *) eroare, și - (void) sesiune URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *).

Prima metodă informează delegatul că sarcina a terminat transferul de date. De asemenea, ar trebui să o utilizați pentru a urmări orice eroare care apare.

 - (void) URLSession: (NSURLSession *) sarcina sesiunii: (NSURLSessionTask *) sarcina didCompleteWithError: (NSError *) eroare if (error == nil) NSLog (task "@ Task:% @ finished";  altceva NSLog (@ "Task:% @ completat cu eroare:% @", task, [error localizedDescription]);  double progress = (dublu) task.countOfBytesReceived / (dublu) task.countOfBytesExpectedToReceive; dispatch_async (dispatch_get_main_queue (), ^ auto.progressView.progress = progress;); auto.downloadTask = nil; 

În cele din urmă, trebuie să adăugați (void) sesiune URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) metodă. Acesta îi spune delegatului că toate mesajele enumerate pentru o sesiune au fost livrate. Ea vă instanțiate AppDelegate pentru a lansa o UILocalNotification. Metoda pe care trebuie să o utilizați este:

 - (void) URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) sesiune AppDelegate * appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegat]; dacă (appDelegate.backgroundSessionCompletionHandler) void (^ completeHandler) () = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = zero; completionHandler ();  NSLog (@ "Toate sarcinile sunt terminate"); 

Vor apărea mai multe erori deoarece nu ați importat încă AppDelegate.h în clasa ta.

 #import "AppDelegate.h"

Deplasați-vă la AppDelegate.h și adăugați următoarele două obiecte:

 @property (puternic, nonatomic) fereastra UIWindow *; @property (copy) void (^ backgroundSessionCompletionHandler) ();

În AppDelegate.m trebuie să implementați metoda delegatului (void) aplicație: (UIApplication *) aplicație handleEventsForBackgroundURLSession: (NSString *) identificator completionHandler: (void (^) () completionHandler. Acesta îi spune delegatului că evenimentele legate de o sesiune de adrese URL așteaptă să fie procesate și apelează o metodă personalizată (presentNotification) pentru a notifica utilizatorul atunci când fișierul se descarcă complet. Metoda completă este:

 - (void) aplicație: (UIApplication *) aplicație handleEventsForBackgroundURLSession: (NSString *) identificator completionHandler: (void (^) ()) completionHandler auto.backgroundSessionCompletionHandler = completionHandler; // adăugați notificarea [self presentOntification]; 

6. Notificare locală

presentNotification utilizează metoda UILocalNotification pentru a crea o notificare locală. Creează un sunet și utilizează sistemul de insigne pentru această notificare. Iată metoda completă:

 -(void) presentNotificarea UILocalNotification * localNotification = [[UILocalNotification alocare] init]; localNotification.alertBody = @ "Descărcare completă!"; localNotification.alertAction = @ "Download de transfer de fond!"; // La sunet localNotification.soundName = UILocalNotificationDefaultSoundName; // crește numărul insignei de aplicație plus 1 localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; [[UIApplication sharedApplication] presentLocalNotificationNow: localNotification]; 

Apropo, pentru a reporni contorul din partea stângă sus la pictograma App, trebuie să adăugați următoarea linie la (void) applicationDidBecomeActive: (UIAapplication *) aplicație metodă în AppDelegate.

 application.applicationIconBadgeNumber = 0;

Notificarea trebuie să fie similară cu următoarea imagine:


Ilustrarea aplicației - Notificare - MTBackgroundTransfer

Acum este timpul să Alerga aplicația și testați descărcarea fundalului.


Concluzie

La sfârșitul acestui tutorial, ați fi terminat serviciul de transfer de fundal în iOS 7. Trebuie să înțelegeți serviciul de transfer de fundal și modul de implementare a acestuia. Dacă aveți întrebări, lăsați-le în secțiunea de comentarii de mai jos.

Cod