iOS 7 SDK service de transfert en arrière-plan

Ce didacticiel vous montrera comment utiliser le service de transfert en arrière-plan, une API multitâche fournie par iOS 7. Je vais vous apprendre à créer une application permettant de télécharger un fichier sans l'application au premier plan. Une fois le fichier téléchargé, un message de notification apparaîtra. Continuer la lecture pour créer ce service!


introduction

Le service de transfert en arrière-plan a été créé avec iOS 6. Cette fonctionnalité permettait aux applications de transférer des fichiers en mode avant-plan et en arrière-plan, mais en limitant le nombre de minutes. Le plus gros problème était lorsque les "minutes limitées" ne permettaient pas à l'utilisateur de télécharger des fichiers volumineux. C'est pourquoi Apple a amélioré le framework sous iOS 7.

Avec iOS 7, cette fonctionnalité a subi des modifications majeures, notamment:

  • iOS gère les téléchargements et les envois
  • Le transfert se poursuit même lorsque l'utilisateur ferme l'application
  • Le temps est illimité
  • Il peut être mis en file d'attente à tout moment (avant-plan et arrière-plan)
  • L'application se réveille pour gérer l'authentification, les erreurs ou l'achèvement
  • L'application comprend une vue de progression

Le service de transfert en arrière-plan peut être utilisé pour plusieurs tâches distinctes et utiles, telles que: télécharger des photos ou des vidéos, combiner la récupération en arrière-plan et les notifications à distance, et mettre à jour l'application, comme pour les achats de livres, d'émissions de télévision, de podcasts, de contenu de jeux, etc. cartes, et plus.


1. Configurer le projet

Pour créer ce service, nous avons besoin d'une vue unique avec les propriétés suivantes:

  • Un ViewController
  • Un contrôleur de navigation
  • Un élément de barre (pour démarrer le téléchargement)
  • Un UIDocumentInterationController (pour ouvrir le téléchargement du document PDF)

Commencez par lancer un nouveau projet iPhone Xcode. Puis créer un Application à vue unique. Ensuite, allez au Main.Storyboard et ajouter des objets à notre Vue. Pour ajouter le Contrôleur de navigation sélectionnez le Contrôleur de vue par défaut. Dans le menu Xcode, sélectionnez Éditeur> Incorporer dans> Contrôleur de navigation. Vous devez glisser-déposer le Article de barre et le Vue de progression à votre contrôleur de vue. Une fois que vous avez terminé, le View Controller devrait ressembler à l'image suivante:


Illustration de l'application - Après la configuration - Transfert en arrière-plan

Ajoutons maintenant les propriétés nécessaires pour interagir avec les objets que nous avons ajoutés. Dans ViewController.h, ajoutez les lignes suivantes:

 @property (faible, non atomique) IBOutlet UIProgressView * progressView; - (IBAction) start: (id) expéditeur;

Maintenant, changez la vue pour le ViewController.m. Un avertissement apparaîtra, mais ne vous en faites pas. nous le réparerons plus tard. Retourner à la Main.Storyboard et connectez les objets avec les propriétés et les actions.

Cette étape est triviale, mais si vous avez des problèmes, n'hésitez pas à utiliser la section commentaires ci-dessous.


2. NSURLSession

le NSURLSession classe et les classes associées fournissent une API pour télécharger ou télécharger du contenu via HTTP. Cette API est responsable de la gestion d'un ensemble de tâches de transfert. Vous devrez créer trois objets directement liés à cette classe: un NSURLSession, NSURLSessionDownloadTask, et UIDocumentInteractionController.

Votre ViewController.h sera quelque chose comme ça:

 @property (nonatomic) NSURLSession * session; @property (nonatomic) NSURLSessionDownloadTask * downloadTask; @property (strong, nonatomic) UIDocumentInteractionController * documentInteractionController;

De plus, vous déclarerez également quatre protocoles: NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate, et UIDocumentInteractionControllerDelegate. Votre @interface devrait ressembler à:

 @interface ViewController: UIViewController < NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate>

Les propriétés que nous ajouterons sont utiles pour instancier et manipuler notre session et le processus de téléchargement, ce qui vous permettra de reprendre, de suspendre, d’annuler ou de récupérer l’état. La dernière propriété, UIDocumentInterationController est utilisé pour présenter le document PDF téléchargé dans ce tutoriel.

Passons maintenant à ViewController.m.

La première tâche à effectuer consiste à ajouter une chaîne à l'emplacement du fichier à télécharger. Vous devez utiliser un fichier Apple PDF standard.

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

Sur le viewDidLoad méthode, instancions et définissons les vues de session et de progression:

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

Puisque vous appelez le backgroundSession méthode, et il n’existe pas, vous devez le déclarer maintenant. Cette méthode est responsable de la distribution d'une action qui sera la session en arrière-plan. le backgroundSession à travers le dispatch_once exécute un bloc une fois pour toute la durée de vie de l'application. le NSString reçu par le NSURLSessionConfiguration représente l'ID de notre session. Cet ID doit être unique pour chaque instance de NSURLSession..

La méthode complète est la suivante:

 - (NSURLSession *) backgroundSession statique NSURLSession * session = nil; static dispatch_once_t onceToken; dispatch_once (& onceToken, ^ NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:] session de retour; 

le (IBAction) start: (id) expéditeur La méthode démarre le téléchargement du document. Vous lancerez alors un NSURL et un NSURLDemande et utiliser le downloadTask propriété de passer l'objet de la demande à la downloadTaskWithRequest méthode. La méthode complète est ci-dessous.

 - (IBAction) start: (id) expéditeur if (self.downloadTask) return;  NSURL * downloadURL = [NSURL URLWithString: DownloadURLString]; NSURLRequest * request = [NSURLRequest requestWithURL: downloadURL]; self.downloadTask = [self.session downloadTaskWithRequest: request]; [self.downloadTask resume]; self.progressView.hidden = NO; 

3. Protocoles

À ce stade, vous remarquerez que trois avertissements sont présents. Ils indiquent que la méthode du protocole doit être implémentée. le NSURLSessionDownloadDelegate Le protocole définit les méthodes pour gérer la tâche de téléchargement. Pour effectuer le téléchargement, il est nécessaire d’utiliser les trois méthodes de délégation..

Alors, ajoutez les trois méthodes suivantes:

  • 1. (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesEcrit totalBytesExpectedToWrite: (int64_t) totalBy
  • 2. (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL
  • 3. (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset attenduTotalBytes: (int64_t) attenduTotalBytes

le (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesEcrit totalBytesExpectedToWrite: (int64_t) totalBytesExpy méthode est responsable de suivre le processus de téléchargement global. Il met également à jour le progressView en conséquence. La méthode complète est ci-dessous.

 - (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) partesWritten totalBytesWritten: (int64_t) double) totalBytesWritten / (double) totalBytesExpectedToWrite; NSLog (@ "DownloadTask:% @ progress:% lf", downloadTask, progress); dispatch_async (dispatch_get_main_queue (), ^ self.progressView.progress = progress;); 

4. Tâche de téléchargement

le (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL méthode traite les données elles-mêmes (origine et destination). Il ne contrôle le fichier qu'une fois qu'il est complètement téléchargé. Pour le dire simplement, cela indique au délégué qu'une tâche de téléchargement est terminée. Il contient la tâche de session terminée, la tâche de téléchargement terminée et une URL de fichier dans laquelle le fichier temporaire peut être trouvé. Ça devrait ressembler à ça:

 - (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL NSFileManager * fileManager = [NSFileManager defaultManager]; NSArray * URLs = [fileManager URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask]; NSURL * documentsDirectory = [URLs objectAtIndex: 0]; NSURL * originalURL = [[downloadTask originalRequest] URL]; NSURL * destinationURL = [documentsDirectory URLByAppendingPathComponent: [originalURL lastPathComponent]]; NSError * errorCopy; // À des fins de test, supprimez tout fichier existant de la destination. [fileManager removeItemAtURL: erreur destinationURL: NULL]; BOOL success = [fileManager copyItemAtURL: downloadURL toURL: erreur destinationURL: & errorCopy]; if (succès) dispatch_async (dispatch_get_main_queue (), ^ // téléchargement terminé - ouvre le fichier pdf self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL: destinationURL]; // Configurez le contrôleur d'interaction de document [self.documentInteractionController set: PDF [self.documentInteractionController presentPreviewAnimated: YES]; self.progressView.hidden = YES;);  else NSLog (@ "Erreur lors de la copie:% @", [errorCopy localizedDescription]); 

Finalement, le (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset attenduTotalBytes: (int64_t) attenduTotalBytes doit également être déclaré. Mais sachez que nous ne l'utilisons plus.

 -(void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset attenduTotalBytes: (int64_t) attenduTotalBytes 

5. Tâches de la session

Vous avez presque fini avec cette classe, il ne reste que deux méthodes: (void) URLSession: (NSURLSession *) tâche de session: (NSURLSessionTask *) tâche didCompleteWithError: (NSError *) error, et - (void) URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) session.

La première méthode informe le délégué que la tâche a fini de transférer les données. Vous devriez également l'utiliser pour suivre toute erreur qui se produit.

 - (void) URLSession: (NSURLSession *) tâche de session: (NSURLSessionTask *) tâche didCompleteWithError: (NSError *) erreur if (erreur == nil) NSLog (@ "Tâche:% @ terminée avec succès", tâche);  else NSLog (@ "La tâche:% @ s'est terminée avec l'erreur:% @", tâche, [erreur localizedDescription]);  double progress = (double) task.countOfBytesReceived / (double) task.countOfBytesExpectedToReceive; dispatch_async (dispatch_get_main_queue (), ^ self.progressView.progress = progress;); self.downloadTask = nil; 

Enfin, vous devez ajouter le (void) URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) session méthode. Il indique au délégué que tous les messages mis en file d'attente pour une session ont été remis. Il instancie votre AppDéléguer afin de lancer un UILocalNotification. La méthode que vous devez utiliser est la suivante:

 - (void) URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) session AppDelegate * appDelegate = (AppDelegate *) [délégué [UIApplication sharedApplication]]]; if (appDelegate.backgroundSessionCompletionHandler) void (^ completionHandler) () = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; AchèvementHandler ();  NSLog (@ "Toutes les tâches sont terminées"); 

Plusieurs erreurs apparaîtront car vous n'avez pas encore importé le fichier AppDelegate.h dans votre classe..

 #import "AppDelegate.h"

Déplacer vers le AppDelegate.h et ajoutez les deux objets suivants:

 @property (strong, nonatomic) UIWindow * fenêtre; @property (copy) void (^ backgroundSessionCompletionHandler) ();

dans le AppDelegate.m vous devez implémenter la méthode delegate application (void): (UIApplication *) application handleEventsForBackgroundURLSession: (NSString *) identificateur CompletionHandler: (void (^) ()) CompletionHandler. Il indique au délégué que des événements liés à une session d'URL attendent d'être traités et appelle une méthode personnalisée (presentNotification) pour informer l'utilisateur lorsque le fichier est complètement téléchargé. La méthode complète est:

 - application (void): (UIApplication *) application handleEventsForBackgroundURLSession: (NSString *) identificateur completionHandler: (void (^) ()) completionHandler self.backgroundSessionCompletionHandler = completionHandler; // add notification [self presentNotification]; 

6. Notification locale

le presentNotification méthode utilise le UILocalNotification classe pour créer une notification locale. Il crée un son et utilise le système de badge pour cette notification. Voici la méthode complète:

 -(void) presentNotification UILocalNotification * localNotification = [[UILocalNotification alloc] init]; localNotification.alertBody = @ "Téléchargement terminé!"; localNotification.alertAction = @ "Télécharger le transfert en arrière-plan!"; // on sound localNotification.soundName = UILocalNotificationDefaultSoundName; // augmente le numéro de badge de l'application plus 1 localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; [[UIApplication sharedApplication] presentLocalNotificationNow: localNotification]; 

Au fait, pour redémarrer le compteur en haut à gauche de l’icône de l’application, vous devez ajouter la ligne suivante à (void) applicationDidBecomeActive: (UIApplication *) application méthode dans le AppDéléguer.

 application.applicationIconBadgeNumber = 0;

La notification devrait ressembler à l'image suivante:


Illustration de l'application - Notification - MTBackgroundTransfer

Il est maintenant temps de Courir l'application et tester le téléchargement en arrière-plan.


Conclusion

À la fin de ce didacticiel, vous devez avoir terminé votre service de transfert en arrière-plan dans iOS 7. Vous devez comprendre le service de transfert en arrière-plan et son implémentation. Si vous avez des questions, s'il vous plaît laissez-les dans la section commentaire ci-dessous.