Dans les tutoriels précédents, nous avons exploré les principes fondamentaux de la NSURLSession
API. Il y a une autre caractéristique de la NSURLSession
API que nous n'avons pas encore examinée, à savoir les téléchargements et téléchargements hors processus. Dans les deux prochains tutoriels, je vais vous montrer comment créer un client de podcast très simple permettant des téléchargements en arrière-plan..
Le client de podcast que nous sommes sur le point de créer ne sera pas vraiment fonctionnel. Cela permettra à l'utilisateur d'interroger l'API de recherche iTunes pour obtenir une liste de podcasts, de sélectionner un podcast et de télécharger des épisodes. Puisque nous nous concentrons sur le NSURLSession
API, nous n'allons pas lire les épisodes que l'application télécharge.
Le projet vous apprendra toutefois à utiliser des tâches de données et à télécharger des tâches dans une application réelle. Le client podcast activera également les téléchargements en arrière-plan pour lesquels nous allons tirer parti NSURLSession
L'API hors processus de. Nous avons pas mal de choses à faire, alors ne perdons pas de temps et commençons.
Lancez Xcode 5, sélectionnez Nouveau> Projet… du Fichier menu, et choisissez le Application à vue unique modèle dans la liste des modèles d'application iOS. Nommez l'application Singlecast, met le Famille de périphérique à iPhone, et indiquez à Xcode où vous souhaitez enregistrer le projet. Frappé Créer pour créer le projet.
La première chose à faire est de modifier le scénarimage principal du projet. Ouvrir Tableau principal, sélectionnez le seul contrôleur de vue du storyboard, puis choisissez Intégrer dans> Contrôleur de navigation du Éditeur menu. La raison de l'intégration du contrôleur de vue dans un contrôleur de navigation apparaîtra plus tard dans ce didacticiel..
Comme je l’ai mentionné dans l’introduction, pour simplifier les choses, l’utilisateur ne pourra s’abonner qu’à un seul podcast. Commençons par créer le contrôleur de vue de recherche. Sélectionner Nouveau> Fichier… du Fichier menu et choisir Classe Objective-C parmi les options à droite. Nommez la classe MTSearchViewController
et en faire une sous-classe de UIViewController
. Laissez la case à cocher intitulée Avec XIB pour l'interface utilisateur décoché. Indiquez à Xcode où vous souhaitez enregistrer les fichiers de classe et appuyez sur Créer.
Avant de créer l'interface utilisateur, ouvrez le fichier d'en-tête du contrôleur de vue et mettez à jour l'interface de la classe, comme indiqué ci-dessous. Nous précisons que le MTSearchViewController
classe conforme à la UITableViewDataSource
, UITableViewDelegate
, et UISearchBarDelegate
protocoles, nous déclarons deux points de vente, barre de recherche
et tableView
ainsi qu'une action, Annuler
, renvoyer le contrôleur de vue de recherche.
#importation@interface MTSearchViewController: UIViewController @property (faible, non atomique) IBOutlet UISearchBar * searchBar; @property (faible, non atomique) IBOutlet UITableView * tableView; - (IBAction) cancel: (id) expéditeur; @fin
Revisitez le scénario principal du projet et faites glisser un nouveau contrôleur de vue du Bibliothèque d'objets sur la droite. Sélectionnez le nouveau contrôleur de vue, ouvrez le Inspecteur d'identité à droite, et définissez la classe du contrôleur de vue sur MTSearchViewController
. Avec le nouveau contrôleur de vue toujours sélectionné, ouvrez le Éditeur menu et choisir Intégrer dans> Contrôleur de navigation. Faites glisser une vue tableau vers la vue du contrôleur de vue et connectez celle-ci la source de données
et déléguer
points de vente avec le contrôleur de vue de recherche.
La vue de tableau étant toujours sélectionnée, ouvrez le Inspecteur d'attributs, et définir le nombre de cellules prototypes à 1
. Sélectionnez la cellule prototype et définissez sa propriété de style sur Sous-titre et son identifiant SearchCell
.
Faites glisser une barre de recherche du Bibliothèque d'objets et l'ajouter à la vue en-tête de la vue tableau. Sélectionnez la barre de recherche et connectez son déléguer
prise avec le contrôleur de vue.
Sélectionnez le contrôleur de vue et connectez son barre de recherche
et tableView
points de vente avec la barre de recherche et la vue tableau, respectivement. Il y a quelques autres choses que nous devons faire avant que nous ayons fini avec le storyboard.
Ouvrez le Bibliothèque d'objets et faites glisser un élément du bouton de la barre vers la barre de navigation. Sélectionnez le bouton barre, connectez-le avec le bouton Annuler:
l'action que nous avons déclarée dans l'interface du contrôleur de vue de recherche, et changer son Identifiant dans le Inspecteur d'attributs à Annuler.
Faites glisser un élément de bouton dans la barre de navigation du contrôleur de vue (pas le contrôleur de recherche) et modifiez son Identifiant dans le Inspecteur d'attributs à Ajouter. Faites glisser le bouton de la barre vers le contrôleur de navigation du contrôleur de vue de recherche, puis sélectionnez modal dans le menu qui apparaît. Cela crée une transition entre le contrôleur de vue et le contrôleur de navigation du contrôleur de vue de recherche..
Si vous deviez contrôler le glissement du bouton de la barre du contrôleur de vue directement sur le contrôleur de vue de recherche au lieu de son contrôleur de navigation, le contrôleur de navigation ne serait jamais instancié et vous ne verriez pas de barre de navigation en haut du contrôleur de vue de recherche..Avant de mettre en œuvre le UITableViewDataSource
et UITableViewDelegate
protocoles dans le MTSearchViewController
classe, nous devons déclarer une propriété qui stocke les résultats de la recherche que nous allons récupérer à partir de l’API de recherche iTunes. Nommez la propriété podcasts
comme indiqué ci-dessous. Nous déclarons également une chaîne statique qui servira d'identifiant de réutilisation de cellule. Il correspond à l'identifiant que nous avons défini sur la cellule prototype il y a quelques instants..
#import "MTSearchViewController.h" @interface MTSearchViewController () @property (strong, nonatomic) NSMutableArray * podcasts; @fin
static NSString * SearchCell = @ "SearchCell";
L'implémentation de numberOfSectionsInTableView:
est aussi facile que cela devient. Nous retournons 1
si self.podcasts
n'est pas néant
et 0
Si c'est. L'implémentation de tableView: numberOfRowsInSection:
est assez similaire comme vous pouvez le voir ci-dessous. Dans tableView: cellForRowAtIndexPath:
, nous demandons à la vue table pour une cellule en passant l'identifiant de réutilisation de la cellule, que nous avons déclaré précédemment, et indexPath
. Nous allons chercher l'article correspondant à partir du podcasts
source de données et mettre à jour la cellule de la vue tableau. Tous les deux tableView: canEditRowAtIndexPath:
et tableView: canMoveRowAtIndexPath:
revenir NON
.
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.podcasts? dix;
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section return self.podcasts? self.podcasts.count: 0;
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SearchCell pourIndexPath: indexPath]; // Récupérer le podcast NSDictionary * podcast = [self.podcasts objectAtIndex: indexPath.row]; // Configurer la cellule de la vue tableau [cell.textLabel setText: [podcast objectForKey: @ "collectionName"]]; [cell.detailTextLabel setText: [podcast objectForKey: @ "artistName"]]; cellule de retour;
- (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO;
- (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO;
Avant d’exécuter l’application, implémentez le Annuler:
action dans laquelle nous rejetons le contrôleur de vue de recherche.
- (IBAction) annuler: (id) expéditeur [auto-licenciement ViewControllerAnimated: YES complétion: nil];
Générez le projet et exécutez l'application pour vous assurer que la fondation fonctionne comme prévu. Il est temps de commencer à utiliser le NSURLSession
API permettant d'interroger l'API iTunes Search.
Commençons par déclarer deux propriétés privées supplémentaires dans le MTSearchViewController
classe, session
et dataTask
. le session
variable est utilisée pour stocker une référence à la NSURLSession
exemple, nous utiliserons pour interroger l’API d’Apple. Nous conservons également une référence à la tâche de données que nous utiliserons pour la demande. Cela nous permettra d'annuler la tâche de données si l'utilisateur met à jour la requête de recherche avant que nous ayons reçu une réponse de l'API. Si vous avez le souci du détail, vous avez peut-être remarqué que le MTSearchViewController
classe est également conforme à la UIScrollViewDelegate
protocole. La raison de ceci deviendra claire dans quelques minutes.
#import "MTSearchViewController.h" @interface MTSearchViewController ()@property (strong, nonatomic) NSURLSession * session; @property (strong, nonatomic) NSURLSessionDataTask * dataTask; @property (strong, nonatomic) podcasts NSMutableArray *; @fin
La session est créée dans sa méthode de lecture, comme vous pouvez le voir ci-dessous. Son implémentation ne devrait pas vous surprendre si vous avez lu les tutoriels précédents. Nous substituons la méthode getter du session
Cette propriété permet de charger paresseusement la session et de limiter l’instanciation et la configuration de la session dans sa méthode getter. Cela rend le code propre et élégant.
- (NSURLSession *) session if (! _Session) // Initialiser la configuration de session NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Configuration de la session [sessionConfiguration setHTTPAdditionalHeaders: @ @ "Accepter": @ "application / json"]; // Initialize Session _session = [NSURLSession sessionWithConfiguration: sessionConfiguration]; return _session;
Pour répondre à la saisie de l'utilisateur dans la barre de recherche, nous implémentons Barre de recherche: textDidChange:
du UISearchBarDelegate
protocole. La mise en œuvre est simple. Si searchText
est néant
, la méthode revient tôt. Si la longueur de searchText
est inférieure à quatre caractères, nous réinitialisons la recherche en appelant Réinitialiser la recherche
. Si la requête comporte quatre caractères ou plus, nous effectuons une recherche en appelant performSearch
sur le contrôleur de vue de recherche.
- (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchText if (! searchText) return; si (searchText.length <= 3) [self resetSearch]; else [self performSearch];
Avant que nous inspections performSearch
, jetons un coup d'œil à Réinitialiser la recherche
. Tout ce que nous faisons dans Réinitialiser la recherche
efface le contenu de podcasts
et recharger la vue table.
- (void) resetSearch // Mettre à jour la source de données [self.podcasts removeAllObjects]; // Mise à jour de la vue de table [self.tableView reloadData];
Le levage de charges lourdes se fait en performSearch
. Après avoir stocké l’entrée de l’utilisateur dans une variable nommée question
, on vérifie si dataTask
est réglé. Si elle est définie, nous appelons Annuler
dessus. C’est important car nous ne voulons pas recevoir de réponse d’un vieux demande qui peut ne plus être pertinente pour l'utilisateur. C'est également la raison pour laquelle nous n'avons qu'une seule tâche de données active à la fois. Il n'y a aucun avantage à envoyer plusieurs requêtes à l'API..
Ensuite, nous demandons à la session une nouvelle instance de tâche de données en lui passant un NSURL
instance et un gestionnaire d'achèvement. N'oubliez pas que la session est la fabrique qui crée les tâches. Vous ne devriez jamais créer de tâches vous-même. Si nous obtenons une tâche de données valide de la session, nous appelons CV
sur ce que nous avons vu dans les tutoriels précédents.
La logique à l'intérieur du gestionnaire d'achèvement est pour le moins intéressante. le Erreur
L'objet est important pour nous pour plusieurs raisons. Cela nous indiquera non seulement si quelque chose ne va pas avec la demande, mais cela est également utile pour déterminer si la tâche de données a été annulée. Si nous obtenons un objet d'erreur, nous vérifions si son code d'erreur est égal à -999
. Ce code d'erreur indique que la tâche de données a été annulée. Si nous obtenons un autre code d'erreur, nous enregistrons l'erreur dans la console. Dans une application réelle, vous devez améliorer la gestion des erreurs et avertir l'utilisateur lorsqu'une erreur est générée..
Si aucune erreur n'a été transmise au gestionnaire d'achèvement, nous créons un dictionnaire à partir du NSData
exemple qui a été passé au gestionnaire d’achèvement et nous en extrayons les résultats. Si nous avons un tableau de résultats à utiliser, nous le transmettons à processResults:
. Avez-vous remarqué que nous avons invoqué processResults:
dans un bloc GCD (Grand Central Dispatch)? Pourquoi avons-nous fait ça? J'espère que vous vous en souvenez, car c'est un détail très important. Nous n'avons aucune garantie que le gestionnaire d'achèvement soit appelé sur le thread principal. Puisque nous devons mettre à jour la vue de table sur le fil principal, nous devons nous assurer que processResults:
est appelé sur le fil principal.
- (void) performSearch NSString * query = self.searchBar.text; if (self.dataTask) [self.dataTask cancel]; self.dataTask = [self.session dataTaskWithURL: [self urlForQuery: query] completionHandler: ^ (données NSData *, réponse NSURLResponse *, erreur NSError *) if (erreur) if (error.code! = -999) NSLog (@ "% @", erreur); else NSDictionary * result = [NSJSONSerialization JSONObjectWithData: options de données: 0 erreur: nil]; NSArray * results = [result objectForKey: @ "results"]; dispatch_async (dispatch_get_main_queue (), ^ if (résultats) [self processResults: results];); ]; if (self.dataTask) [self.dataTask resume];
Avant de regarder la mise en œuvre de processResults:
, Je veux vous montrer rapidement ce qui se passe dans urlForQuery:
, la méthode d'assistance que nous utilisons dans performSearch
. Dans urlForQuery:
, nous remplaçons les espaces par un +
signez pour vous assurer que l'API iTunes Search est satisfait de ce que nous l'envoyons. Nous créons ensuite un NSURL
par exemple avec et le retourner.
- (NSURL *) urlForQuery: (NSString *) requête requête = [requête stringByReplacingOcurrencesOfString: @ "" withString: @ "+"]; return [NSURL URLWithString: [NSString stringWithFormat: @ "https://itunes.apple.com/search?media=podcast&entity=podcast&term=%@", requête]];
Dans processResults:
, la podcasts
la variable est effacée, renseignée avec le contenu de résultats
, et les résultats sont affichés dans la vue tableau.
- (void) processResults: (NSArray *) résultats if (! self.podcasts) self.podcasts = [tableau NSMutableArray]; // Mettre à jour la source de données [self.podcasts removeAllObjects]; [self.podcasts addObjectsFromArray: results]; // Mise à jour de la vue de table [self.tableView reloadData];
Lorsque l'utilisateur appuie sur une ligne de la vue tableau pour sélectionner un podcast, tableView: didSelectRowAtIndexPath:
du UITableViewDelegate
le protocole est appelé. Sa mise en œuvre peut sembler étrange au début, alors laissez-moi vous expliquer ce qui se passe. Nous sélectionnons le podcast qui correspond à la sélection de l'utilisateur, nous l'enregistrons dans la base de données par défaut de l'application et nous rejetons le contrôleur de vue de recherche. Nous n'en informons personne? Pourquoi nous faisons cela deviendra clair une fois que nous continuerons à mettre en œuvre les MTViewController
classe.
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath [tableView deselectRowAtIndexPath: indexPath animé: YES]; // Récupérer le podcast NSDictionary * podcast = [self.podcasts objectAtIndex: indexPath.row]; // Mise à jour des valeurs utilisateur NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; [ud setObject: podcast forKey: @ "MTPodcast"]; [ud synchronize]; // Dismiss View Controller [autoJViewViewControllerAnimated: YES complétion: nil];
Je veux parler de deux détails avant de revenir à la MTViewController
classe. Lorsque le contrôleur de vue de recherche est présenté à l'utilisateur, il est clair qu'il souhaite rechercher des podcasts. C'est donc une bonne idée de présenter immédiatement le clavier. Nous faisons cela dans viewDidAppear:
comme indiqué ci-dessous.
- (void) viewDidAppear: (BOOL) animated [super viewDidAppear: animated]; // Afficher le clavier [self.searchBar devientFirstResponder];
Le clavier doit masquer le moment où l'utilisateur commence à faire défiler les résultats de la recherche. Pour ce faire, nous mettons en œuvre scrollViewDidScroll:
du UIScrollViewDelegate
protocole. Ceci explique pourquoi MTSearchViewController
conforme à la UIScrollViewDelegate
protocole. Regardez l'implémentation de scrollViewDidScroll:
indiqué ci-dessous.
- (void) scrollViewDidScroll: (UIScrollView *) scrollView if ([self.searchBar isFirstResponder]) self.searchBar resignFirstResponder];le
UITableView
classe est une sous-classe de UIScrollView
, quelle est la raison pour laquelle l'approche ci-dessus fonctionne. Comme nous l'avons vu précédemment, nous stockons la sélection de l'utilisateur dans la base de données par défaut de l'application. Nous devons mettre à jour le MTViewController
classe pour utiliser la sélection de l'utilisateur dans le contrôleur de vue de recherche. Dans le contrôleur de vue viewDidLoad
méthode, nous chargeons le podcast à partir de la base de données par défaut de l'utilisateur et ajoutons le contrôleur de vue en tant qu'observateur de la base de données par défaut de l'utilisateur pour le chemin d'accès à la clé MTPodcast
de sorte que le contrôleur de vue soit averti lorsque la valeur de MTPodcast
changements.
- (void) viewDidLoad [super viewDidLoad]; // Chargement du podcast [self loadPodcast]; // Add Observer [[NSUserDefaults standardUserDefaults] addObserver: self forKeyPath: @ options "MTPodcast": NSKeyValueObservingOptionNew context: NULL];
Tout ce que nous faisons dans loadPodcast
stocke la valeur pour MTPodcast
à partir de la base de données par défaut de l'utilisateur dans le contrôleur de vue Podcast
propriété. Cette valeur sera néant
si la base de données par défaut de l'utilisateur ne contient pas d'entrée pour MTPodcast
. Le contrôleur de vue gérera cela avec élégance pour nous. Rappelez-vous qu’en Objective-C, vous pouvez envoyer des messages à néant
sans que l'enfer se déchaîne. Cela a ses inconvénients, mais il a certainement ses avantages à.
- (void) loadPodcast NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; self.podcast = [ud objectForKey: @ "MTPodcast"];
Cela signifie également que nous devons déclarer une propriété nommée Podcast
dans le fichier d'implémentation du contrôleur de vue.
#import "MTViewController.h" @interface MTViewController () @property (strong, nonatomic) NSDictionary * podcast; @fin
Regardons aussi rapidement setPodcast:
et updateView
.
- (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Mise à jour de la vue [self updateView];
- (void) updateView // Vue de la mise à jour self.title = [self.podcast objectForKey: @ "nom de la collection"];
Lorsque la valeur dans la base de données utilisateur par défaut change pour la clé MTPodcast
, le contrôleur de vue peut répondre à ce changement de observeValueForKeyPath: ofObject: change: context:
. C'est ainsi que l'observation des valeurs clés fonctionne. Tout ce que nous faisons dans cette méthode est de mettre à jour la valeur du contrôleur de vue Podcast
propriété.
- (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) modification d'objet: (NSDictionary *) changement de contexte: (void *) contexte if ([keyPath isEqualToString: @ "MTPodcast"]) self.podcast = [object objectForKey: @ "MTPodcast"];
Lorsque vous utilisez l'observation des valeurs clés, il est essentiel de prendre conscience de la gestion de la mémoire et de conserver les cycles. Dans ce cas, cela signifie que nous devons supprimer le contrôleur de vue en tant qu'observateur lorsque le contrôleur de vue est désalloué..
- (void) dealloc [[[NSUserDefaults standardUserDefaults]] removeObserver: self forKeyPath: @ "MTPodcast"];
La réponse que nous recevons de l’API de recherche iTunes inclut un URL du flux
attribut pour chaque podcast. Nous pourrions récupérer le flux manuellement et l’analyser. Cependant, pour gagner du temps, nous allons utiliser MWFeedParser, une bibliothèque populaire qui peut le faire pour nous. Vous pouvez télécharger et inclure manuellement la bibliothèque dans votre projet, mais je vais opter pour les Cocoapods. Je préfère les Cocoapods pour la gestion des dépendances dans les projets iOS et OS X. Vous pouvez en savoir plus sur Cocoapods sur son site web ou sur Mobiletuts+.
Quittez Xcode, accédez à la racine de votre projet Xcode et créez un fichier nommé Podfile. Ouvrez ce fichier dans l'éditeur de texte de votre choix et ajoutez les trois lignes de code suivantes. Dans la première ligne, nous spécifions la plate-forme et la cible de déploiement, qui est iOS 7 dans cet exemple. Les deux lignes suivantes spécifient chacune une dépendance de notre projet Xcode. Le premier est le MWFeedParser bibliothèque et j'ai aussi inclus le populaire SVProgressHUD bibliothèque, qui sera utile un peu plus tard.
plate-forme: ios, '7' pod 'MWFeedParser' pod 'SVProgressHUD'
Ouvrez une fenêtre de terminal, accédez à la racine de votre projet Xcode et exécutez la commande installation de pod
. Cela devrait installer les dépendances et créer un espace de travail Xcode.. Lorsque Cocoapods a fini d’installer les dépendances du projet, il vous indique d’utiliser l’espace de travail qu’il a créé pour vous. Ceci est important alors n'ignore pas ce conseil. À la racine de votre projet Xcode, vous verrez que Cocoapods a en effet créé un espace de travail Xcode pour vous. Double-cliquez sur ce fichier et vous devriez être prêt à partir.
Ouvrez le fichier d'implémentation du MTViewController
classe, ajoutez une déclaration d'importation pour MWFeedParser et SVProgressHUD, et déclarer deux propriétés, épisodes
et feedParser
. Nous devons aussi faire MTViewController
se conformer à la MWFeedParserDelegate
protocole.
#import "MTViewController.h" #import "MWFeedParser.h" #import "SVProgressHUD.h" @interface MTViewController ()@property (strong, nonatomic) NSDictionary * podcast; @property (strong, nonatomic) épisodes NSMutableArray *; @property (strong, nonatomic) MWFeedParser * feedParser; @fin
Ensuite, nous mettons à jour setPodcast:
en invoquant fetchAndParseFeed
, une méthode d'assistance dans laquelle nous utilisons le MWFeedParser
classe pour récupérer et analyser le flux du podcast.
- (void) setPodcast: (NSDictionary *) podcast if (_podcast! = podcast) _podcast = podcast; // Mise à jour de la vue [self updateView]; // Récupération et analyse de flux [self fetchAndParseFeed];
Dans fetchAndParseFeed
, nous nous débarrassons de notre courant MWFeedParser
exemple si nous en avons un et initialisons une nouvelle instance avec l’URL du flux du podcast. Nous avons mis le feedParseType
propriété à ParseTypeFull
et définissez le contrôleur de vue en tant que délégué de l'analyseur de flux. Avant de récupérer le flux, nous utilisons SVProgressHUD
montrer un progrès à l'utilisateur.
- (void) fetchAndParseFeed if (! self.podcast) return; NSURL * url = [NSURL URLWithString: [self.podcast objectForKey: @ "feedUrl"]]; si (! url) retourne; if (self.feedParser) [self.feedParser stopParsing]; [self.feedParser setDelegate: nil]; [self setFeedParser: nil]; // Effacer les épisodes if (self.episodes) [self setEpisodes: nil]; // Initialisation de l'analyseur de flux self.feedParser = [[MWFeedParser alloc]] initWithFeedURL: url]; // Configurer l'analyseur de flux [self.feedParser setFeedParseType: ParseTypeFull]; [self.feedParser setDelegate: self]; // Afficher la palette de progression [SVProgressHUD showWithMaskType: SVProgressHUDMaskTypeGradient]; // Démarrer l'analyse [self.feedParser parse];
Nous devons également mettre en œuvre deux méthodes de MWFeedParserDelegate
protocole, feedParser: didParseFeedItem:
et feedParserDidFinish:
. Dans feedParser: didParseFeedItem:
, on initialise le épisodes
propriété si nécessaire et transmettez-lui l'élément de fil que l'analyseur de flux nous tend.
- (void) feedParser: (MWFeedParser *) analyseur didParseFeedItem: (MWFeedItem *) item if (! self.episodes) self.episodes = [tableau NSMutableArray]; [self.episodes addObject: item];
Dans feedParserDidFinish:
, nous rejetons le HUD de progression et mettons à jour la vue tableau. Avez-vous dit vue de la table? C'est vrai. Nous devons ajouter une vue de table et mettre en œuvre le nécessaire UITableViewDataSource
méthodes de protocole.
- (void) feedParserDidFinish: (MWFeedParser *) parser // Refuser le HUD de progression [SVProgressHUD ignorer]; // Mise à jour de la vue [self.tableView reloadData];
Avant de mettre à jour l'interface utilisateur, ouvrez MTViewController.h
, déclarez un point de vente pour la vue table et dites au compilateur le MTViewController
classe conforme à la UITableViewDataSource
et UITableViewDelegate
les protocoles.
#importation@interface MTViewController: UIViewController @property (faible, non atomique) IBOutlet UITableView * tableView; @fin
Ouvrez le scénario principal une fois de plus et ajoutez une vue tabulaire à la vue du contrôleur de vue. Connecter la vue de la table la source de données
et déléguer
prises avec le contrôleur de vue et connecter le contrôleur de vue tableView
sortie avec la vue de la table. Sélectionnez la vue tableau, ouvrez le Inspecteur d'attributs, et définir le nombre de cellules prototypes à 1
. Sélectionnez la cellule prototype, définissez son style sur Sous-titre, et lui donner un identifiant de EpisodeCell.
Avant de mettre en œuvre le UITableViewDataSource
protocole, déclarer une chaîne statique nommée EpisodeCell
dans MTViewController.m. Cela correspond à l'identifiant que nous avons défini pour la cellule prototype dans le storyboard..
static NSString * EpisodeCell = @ "EpisodeCell";
Mise en œuvre du UITableViewDataSource
Le protocole est simple comme bonjour et très similaire à la façon dont nous avons implémenté le protocole dans le contrôleur de vue de recherche. La seule différence est que le épisodes
la variable contient des occurrences du MWFeedItem
classe au lieu de NSDictionary
les instances.
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return self.episodes? dix;
- (NSInteger) tableView: (UITableView *) table numéroViewOfRowsInSection: (NSInteger) section return self.episodes? self.episodes.count: 0;
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: EpisodeCell pourIndexPath: indexPath]; // Récupération d'un élément de fil MWFeedItem * feedItem = [self.episodes objectAtIndex: indexPath.row]; // Configure Table View Cell [cell.textLabel setText: feedItem.title]; [cell.detailTextLabel setText: [NSString stringWithFormat: @ "% @", feedItem.date]]; cellule de retour;
- (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO;
- (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return