Réseautage avec NSURLSession Partie 1

Du point de vue du développeur, l’un des changements les plus significatifs dans iOS 7, et OS X Mavericks, est l’introduction de NSURLSession. Même si NSURLSession peut sembler intimidant au premier abord, il est important que vous compreniez ce que c'est, comment ça se rapporte NSURLConnection, et quelles sont les différences. Dans cette série, je vais vous présenter les principes fondamentaux de NSURLSession afin que vous puissiez tirer parti de cette nouvelle technologie dans vos propres applications.


Pourquoi remplacer NSURLConnection?

La première question que vous vous posez peut-être est de savoir pourquoi Apple a jugé nécessaire de présenter NSURLSession alors que nous sommes parfaitement heureux avec NSURLConnection. La vraie question est de savoir si vous sont heureux avec NSURLConnection. Vous souvenez-vous du moment où vous avez maudit et jeté des choses à NSURLConnection? La plupart des développeurs de Cocoa se sont rendus à cet endroit. C'est pourquoi Apple a décidé de revenir au tableau et de créer une solution plus élégante, mieux adaptée au Web moderne.

Même si NSURLSession et NSURLConnection ont beaucoup en commun en ce qui concerne la façon dont ils travaillent, à un niveau fondamental, ils sont très différents. Apple a créé NSURLSession ressembler aux concepts généraux de NSURLConnection, mais vous apprendrez au cours de cette série que NSURLSession est moderne, facile à utiliser et conçu pour le mobile.


Quel est NSURLSession?

Avant de discuter des différences entre NSURLSession et NSURLConnection, c'est une bonne idée de regarder d'abord de plus près ce que NSURLSession est. Malgré son nom, NSURLSession n'est pas simplement une autre classe que vous pouvez utiliser dans une application iOS ou OS X. NSURLSession est avant tout une technologie au même titre que NSURLConnection est.

Les sessions sont des conteneurs

NSURLSession et NSURLConnection les deux fournissent une API pour interagir avec divers protocoles, tels que HTTP et HTTPS. L'objet de session, une instance de NSURLSession classe, est ce qui gère cette interaction. Il s’agit d’un conteneur hautement configurable avec une API élégante qui permet un contrôle précis. Il offre des fonctionnalités qui sont absentes dans NSURLConnection. De plus, avec NSURLSession, vous pouvez accomplir des tâches qui ne sont tout simplement pas possibles avec NSURLConnection, comme la mise en œuvre de la navigation privée.

les tâches

L'unité de travail de base lorsque vous travaillez avec NSURLSession est la tâche, une instance de NSURLSessionTask. Il y a trois types de tâches, tâches de données, télécharger des tâches, et tâches de téléchargement.

  • Vous utiliserez le plus souvent des tâches de données, qui sont des instances de NSURLSessionDataTask. Les tâches de données sont utilisées pour demander des données à un serveur, telles que des données JSON. La principale différence entre les tâches de téléchargement et de téléchargement est qu'elles renvoient des données directement à votre application au lieu de passer par le système de fichiers. Les données ne sont stockées qu'en mémoire.
  • Comme son nom l'indique, les tâches de téléchargement sont utilisées pour télécharger des données vers une destination distante. le NSURLSessionUploadTask est une sous-classe de NSURLSessionDataTask et se comporte de la même manière. L'une des principales différences avec une tâche de données classique est que les tâches de téléchargement peuvent être utilisées dans une session créée avec une configuration de session en arrière-plan..
  • Télécharger des tâches, des instances de NSURLSessionDownloadTask, hériter directement de NSURLSessionTask. La différence la plus significative avec les tâches de données est qu'une tâche de téléchargement écrit sa réponse directement dans un fichier temporaire. Ceci est très différent d'une tâche de données normale qui stocke la réponse en mémoire. Il est possible de Annuler une tâche de téléchargement et CV plus tard.

Comme vous pouvez l’imaginer, l’asynchronisme est un concept clé dans NSURLSession. le NSURLSession L'API renvoie des données en appelant un gestionnaire de complétion ou par l'intermédiaire du délégué de la session. L'API de NSURLSession a été conçu pour être flexible, comme vous le remarquerez un peu plus tard dans ce tutoriel.

Rencontrer la famille

Comme je l'ai mentionné plus tôt, NSURLSession est à la fois une technologie et une classe avec laquelle vous travaillerez. le NSURLSession L’API héberge un certain nombre de classes, mais NSURLSession est le composant clé qui envoie les demandes et reçoit les réponses. Cependant, la configuration de l’objet de session est gérée par une instance de NSURLSessionConfiguration classe. le NSURLSessionTask La classe et ses trois sous-classes concrètes sont les travaux et sont toujours utilisées conjointement avec une session car c'est la session qui crée les objets de tâche..

Délégation

Tous les deux NSURLSession et NSURLConnection repose fortement sur le modèle de délégation. le NSURLSessionDelegate Le protocole déclare une poignée de méthodes déléguées pour le traitement des événements au niveau de la session. De plus, le NSURLSessionTask les classes et sous-classes déclarent chacune un protocole délégué pour la gestion des événements au niveau des tâches.

Vieux amis

le NSURLSession L'API repose sur les classes que vous connaissez déjà, telles que NSURL, NSURLDemande, et NSURLResponse.


Quelles sont les différences?

Comment NSURLSession différer NSURLConnection? C’est une question importante, car NSURLConnection n'est pas obsolète par Apple. Vous pouvez toujours utiliser NSURLConnection dans vos projets. Pourquoi devriez-vous utiliser NSURLSession?

La première chose à comprendre est que le NSURLSession instance est l'objet qui gère la demande et la réponse. Ceci est similaire à la façon dont NSURLConnection fonctionne, mais la principale différence est que la configuration de la demande est gérée par l'objet de session, qui est un objet de longue durée. Cela se fait à travers le NSURLSessionConfiguration classe. Non seulement il fournit la NSURLSession API configuration fine à travers le NSURLSessionConfiguration classe, il encourage la séparation des données (corps de la demande) et des métadonnées. le NSURLSessionDownloadTask illustre bien ceci en écrivant directement la réponse dans le système de fichiers.

L’authentification est plus facile et gérée plus élégamment par NSURLSession. le NSURLSession L'API gère l'authentification sur une base de connexion plutôt que sur une base de demande, comme NSURLConnection Est-ce que. le NSURLSession L'API facilite également la fourniture d'options HTTP et chaque session peut avoir un conteneur de stockage distinct en fonction de la configuration de la session..

Dans l'introduction, je vous ai dit que NSURLSession fournit une interface moderne, qui s'intègre harmonieusement à iOS 7. Un exemple de cette intégration est NSURLSessionLes envois et téléchargements hors processus. NSURLSession est optimisé pour préserver la durée de vie de la batterie, prend en charge les pauses, les annulations et la reprise des tâches, ainsi que l’API multitâche de UIKit. De quoi ne pas aimer NSURLSession?


Se mouiller les pieds

Étape 1: Configuration du projet

Il est préférable d’apprendre une nouvelle API, il est donc temps de lancer Xcode et de nous mouiller les pieds. Lancez Xcode 5, créez un nouveau projet en sélectionnant Nouveau> Projet… du Fichier menu et sélectionnez le Application à vue unique modèle de la liste des modèles d'application iOS.


Donnez un nom à votre projet, dites à Xcode où vous souhaitez l’enregistrer, puis appuyez sur Créer. Il n'est pas nécessaire de placer le projet sous contrôle de source.


Étape 2: Créer un objet de session

Quand on travaille avec NSURLSession, il est important de comprendre que l'objet de session, une instance de NSURLSession, est le joueur star. Il traite les demandes et les réponses, configure les demandes, gère le stockage et l'état de la session, etc. La création d'une session peut s'effectuer de plusieurs manières. Le moyen le plus rapide de commencer est d’utiliser NSURLSessionde session partagée méthode de classe comme indiqué ci-dessous.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; 

Créer un session objet dans le contrôleur de vue viewDidLoad méthode indiquée ci-dessus. le session L'objet que nous avons créé convient à notre exemple, mais vous souhaitez probablement un peu plus de flexibilité dans la plupart des cas. le session objet que nous venons de créer utilise le global NSURLCache, NSHTTPCookieStorage, et NSURLCredentialStorage. Cela signifie que cela fonctionne assez similaire à une implémentation par défaut de NSURLConnection.

Étape 3: créer une tâche de données

Mettre le session objet à utiliser, interrogons l'API iTunes Store Search et recherchons les logiciels conçus par Apple. L'API de recherche iTunes Store est facile à utiliser et ne nécessite aucune authentification, ce qui le rend idéal pour notre exemple..

Pour interroger l’API de recherche, nous devons envoyer une demande à https://itunes.apple.com/search et passer quelques paramètres. Comme nous l’avons vu précédemment, lorsqu’on utilise le NSURLSession API, une requête est représentée par une tâche. Pour interroger l’API de recherche, il suffit d’une tâche de données, d’une instance du NSURLSessionDataTask classe. Jetez un coup d'oeil à la mise à jour viewDidLoad mise en œuvre ci-dessous.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "http: NSDictionary * json = [NSJSONSerialization JSONObjectWithData: options de données: 0 erreur: nil]; NSLog (@ "% @", json); ]; 

Il existe un certain nombre de méthodes disponibles pour créer une tâche, mais le concept clé à comprendre est que le session object effectue la création et la configuration réelles de la tâche. Dans cet exemple, nous appelons dataTaskWithURL: completionHandler: et passez une instance de NSURL ainsi qu'un gestionnaire de complétion. Le gestionnaire d’achèvement accepte trois arguments, le données brutes de la réponse (NSData), la objet de réponse (NSURLResponse), Et un objet d'erreur (NSError). Si la requête aboutit, l'objet d'erreur est néant. Comme nous savons que la demande renvoie une réponse JSON, nous créons un Fondation objet de la Les données objet que nous avons reçu et connectons la sortie à la console.

Il est important de comprendre que le Erreur L’objet passé au gestionnaire d’achèvement n’est rempli que, pas néant, si la demande a échoué ou a rencontré une erreur. En d’autres termes, si la requête renvoie un 404 réponse, la demande a abouti en ce qui concerne les sessions. le Erreur l'objet sera alors néant. C’est un concept important à saisir lorsque vous travaillez avec NSURLSession et NSURLConnection d'ailleurs.

Générez le projet et exécutez l'application dans iOS Simulator ou sur un périphérique physique, puis inspectez la console Xcode. Rien n'est imprimé sur la console. Qu'est ce qui ne s'est pas bien passé? Comme je l'ai mentionné plus tôt, le NSURLSession L'API prend en charge la pause, l'annulation et la reprise de tâches ou de demandes. Ce comportement est similaire à celui de NSOperation et cela peut vous rappeler la bibliothèque AFNetworking. Une tâche a Etat propriété qui indique si la tâche est fonctionnement (NSURLSessionTaskStateRunning), suspendu (NSURLSessionTaskStateSuspended), annulation (NSURLSessionTaskStateCanceling), ou terminé (NSURLSessionTaskStateCompleted). Lorsqu'un objet de session crée une tâche, celle-ci commence sa vie dans le suspendu Etat. Pour commencer la tâche, nous devons lui dire CV en appelant CV sur la tâche. Mettre à jour le viewDidLoad comme indiqué ci-dessous, exécutez l'application une fois de plus et inspectez la sortie dans la console. Mission accomplie.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL: [NSURL URLWithString: @ "http: NSDictionary * json = [NSJSONSerialization JSONObjectWithData: options de données: 0 erreur: nil]; NSLog (@ "% @", json); ]; [dataTask resume]; 

Téléchargement d'une ressource distante

Dans l'exemple précédent, nous avons utilisé un gestionnaire d'achèvement pour traiter la réponse reçue à partir de la demande. Il est également possible d'obtenir le même résultat en implémentant le (s) protocole (s) de délégation de tâche. Voyons ce qu'il faut pour télécharger une image en tirant parti de NSURLSession et le NSURLSessionDownloadTask.

Étape 1: Créer l'interface utilisateur

Ouvrir MTViewController.h et créez deux sorties comme indiqué ci-dessous. Nous allons utiliser le premier point de vente, une instance de UIImageView, pour afficher l'image téléchargée à l'utilisateur. Le second point de vente, une instance de UIProgressView, montrera la progression de la tâche de téléchargement.

 #importation  @interface MTViewController: UIViewController @property (faible, non atomique) IBOutlet UIImageView * imageView; @property (faible, non atomique) IBOutlet UIProgressView * progressView; @fin

Ouvrez le scénario principal du projet (Tableau principal), faites glisser un UIImageView exemple à la vue du contrôleur de vue et connectez la sortie du contrôleur de vue que nous venons de créer dans le fichier d’en-tête du contrôleur de vue. Répétez cette procédure pour la vue de progression.


Étape 2: Créer une tâche de téléchargement

Dans cet exemple, nous ne ferons pas usage de la session partagée méthode de classe, car nous avons besoin de configurer le session objet que nous allons utiliser pour faire la demande. Mettre à jour la mise en œuvre de viewDidLoad comme indiqué ci-dessous.

 - (void) viewDidLoad [super viewDidLoad]; NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession * session = [NSURLSession sessionWithConfiguration: sessionConfiguration delegate: self delegateQueue: nil]; NSURLSessionDownloadTask * downloadTask = [session downloadTaskWithURL: [NSURL URLWithString: @ "http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]]; [télécharger le CV de la tâche]; 

Pour éviter tout avertissement du compilateur, assurez-vous de respecter le MTViewController classe à la NSURLSessionDelegate et NSURLSessionDownloadDelegate protocoles comme indiqué ci-dessous.

 #import "MTViewController.h" @interface MTViewController ()  @fin

Dans viewDidLoad, nous créons une instance du NSURLSessionConfiguration classe en invoquant le defaultSessionConfiguration méthode de classe. Comme indiqué dans la documentation, en utilisant la configuration de session par défaut, la session se comportera presque comme une instance de NSURLConnection dans sa configuration par défaut, ce qui convient à notre exemple.

Dans cet exemple, nous créons un NSURLSession par exemple en invoquant le sessionWithConfiguration: delegate: delegateQueue: méthode de classe et passer le sessionConfiguration objet que nous avons créé il y a un moment. Nous définissons le contrôleur de vue comme délégué de session et passons néant comme troisième argument. Vous pouvez ignorer le troisième argument pour le moment. La principale différence avec l'exemple précédent est que nous avons défini le paramètre sessionle délégué du contrôleur de vue.

Pour télécharger l'image, nous devons créer une tâche de téléchargement. Nous faisons cela en appelant downloadTaskWithURL: sur le session objet, en passant une instance de NSURL, et appeler CV sur la tâche de téléchargement. Nous aurions pu utiliser un gestionnaire d'achèvement comme nous l'avons fait plus tôt, mais je veux vous montrer les possibilités d'utiliser un délégué à la place..

Étape 3: Implémenter le protocole de délégué

Pour que tout cela fonctionne, nous devons implémenter les trois méthodes de délégation du NSURLSessionDownloadDelegate protocole, URLSession: downloadTask: didFinishDownloadingToURL:, URLSession: downloadTask: didResumeAtOffset: attenduTotalBytes:, et URLSession: downloadTask: downloadTask didWriteData: totalBytesWritten: totalBytesExpectedToWrite:. La mise en œuvre de chaque méthode est assez facile. Il est important de noter que nous avons besoin de mettre à jour l'interface utilisateur sur le thread principal à l'aide de GCD (Grand Central Dispatch). En passant néant comme troisième argument de sessionWithConfiguration: delegate: delegateQueue:, le système d'exploitation a créé une file d'attente en arrière-plan pour nous. C'est correct, mais cela signifie également que nous devons savoir que les méthodes de délégation sont appelées sur un thread d'arrière-plan au lieu du thread principal. Construisez le projet et lancez l'application pour voir le résultat de notre dur labeur.

 - (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) location NSData * data = [NSData dataWithContentsOfURL: location]; dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setHidden: YES]; [self.imageView setImage: [UIImage imageWithData: data]];);  - (void) URLSession: (NSURLSession *) session downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset attendueTotalBytes: (int64_t) attendueTotalBytes  - (void) URLSession (en cours) (env. downloadTask didWriteData: (int64_t) bytesWritten totalBytesWritten: (int64_t) totalBytesWritten totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite progression du flottement = (double) totalBytesWritten / (double) totalBytes dispatch_async (dispatch_get_main_queue (), ^ [self.progressView setProgress: progress];); 

Conclusion

Avec ces deux exemples, vous devriez avoir une compréhension de base des principes fondamentaux de la NSURLSession API, comment elle se compare à NSURLConnection, et quels sont ses avantages. Dans la prochaine partie de cette série, nous examinerons des fonctionnalités plus avancées de NSURLSession.