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!
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:
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.
Pour créer ce service, nous avons besoin d'une vue unique avec les propriétés suivantes:
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:
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.
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;
À 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:
(void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesEcrit totalBytesExpectedToWrite: (int64_t) totalBy
(void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL
(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;);
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
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];
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:
Il est maintenant temps de Courir
l'application et tester le téléchargement en arrière-plan.
À 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.