{"id":617,"date":"2013-11-10T15:30:27","date_gmt":"2013-11-10T19:30:27","guid":{"rendered":"http:\/\/tim.cstj.qc.ca\/cours\/xcode\/wp\/?page_id=617"},"modified":"2013-11-10T15:30:27","modified_gmt":"2013-11-10T19:30:27","slug":"posttim","status":"publish","type":"page","link":"https:\/\/ve2cuy.com\/xcode\/labo\/posttim\/","title":{"rendered":"Post&#039;TIM"},"content":{"rendered":"<h1>Mise en place d&rsquo;un protocole O.C<\/h1>\n<p>Note: document en cours de r\u00e9vision.<\/p>\n<h2>Contenu<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-625 alignleft\" style=\"margin-right: 50px;\" alt=\"Post'TIM\" src=\"\/xcode\/wp-content\/uploads\/2013\/11\/PostTIM.png\" width=\"241\" height=\"383\" \/><\/p>\n<ul>\n<li>Programmer un protocole O.C.<\/li>\n<li>Programmer l&rsquo;appel de m\u00e9thodes de d\u00e9l\u00e9gation sur &lsquo;respondToSelector&rsquo;.<\/li>\n<li>Enregistrer un NSArray dans un fichier de propri\u00e9t\u00e9s (.plist).<\/li>\n<li>Utiliser un formateur de date pour afficher un NSDate en heure locale.<\/li>\n<li>Programmer plusieurs destinations dans la m\u00e9thode &lsquo;prepareForSegue&rsquo;<\/li>\n<\/ul>\n<p><strong>Pr\u00e9-requis:<\/strong><\/p>\n<ol>\n<li>Avoir compl\u00e9t\u00e9 le tutoriel\u00a0<a href=\"\/xcode\/index.php\/labo\/timflix-delegation-et-uitableview-personnalisee\/\">TIMFlix<\/a>\u00a0ou bien avoir une maitrise de l&rsquo;objet UITableView + segue + passage de param\u00e8tres entre les sc\u00e8nes d&rsquo;une app.<\/li>\n<li>Avoir compl\u00e9t\u00e9 le module <a href=\"..contenu\/les-objets-sous-oc\/\">POO sous OC<\/a><\/li>\n<\/ol>\n<p>&nbsp;<br \/>\n&nbsp;<\/p>\n<hr \/>\n<p>&nbsp;<br \/>\nVid\u00e9o du r\u00e9sultat final:<br \/>\n<iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"http:\/\/www.youtube.com\/embed\/vEt18tY0-mg?feature=oembed\" frameborder=\"0\" allowfullscreen><\/iframe><br \/>\n&nbsp;<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<h1>Description du projet<\/h1>\n<p>Dans ce tutoriel, nous verrons comment construire une application qui permet la gestion d&rsquo;une liste de t\u00e2ches \u00e0 r\u00e9aliser &#8211; pr\u00e9sent\u00e9es dans un &lsquo;UITableView&rsquo; &#8211; , sous forme de m\u00e9mos \u00e9ditables.<br \/>\nLes &lsquo;t\u00e2ches&rsquo; seront lues et enregistr\u00e9es dans un fichier de propri\u00e9t\u00e9s, ce qui assurera leur p\u00e9rennit\u00e9 entre les chargements de l&rsquo;application.<br \/>\nL&rsquo;application proposera une liste de t\u00e2ches \u00e0 partir de laquelle il sera possible:<\/p>\n<ul>\n<li>d&rsquo;ajouter une nouvelle t\u00e2che<\/li>\n<li>de modifier la t\u00e2che courante<\/li>\n<li>d&rsquo;effacer la t\u00e2che courante<\/li>\n<li>de consulter le d\u00e9tail de la t\u00e2che courante.<\/li>\n<\/ul>\n<h1>Objectif principal<\/h1>\n<p>Savoir programmer un &lsquo;protocole&rsquo; sous O.C.<br \/>\nExplication<br \/>\nNous allons programmer un protocole, dans la classe de la sc\u00e8ne &lsquo;ajouter\/modifier&rsquo; qui va permettre \u00e0 la classe de la sc\u00e8ne &lsquo;liste des t\u00e2ches&rsquo; de devenir d\u00e9l\u00e9gu\u00e9 des m\u00e9thodes &lsquo;ajouterTache&rsquo; et &lsquo;modifierTache&rsquo; \u00a0de la classe &lsquo;ajouter-modifier&rsquo;.<\/p>\n<h1>Objectifs secondaires<\/h1>\n<p>\u00c0 d\u00e9finir &#8230;<br \/>\n&nbsp;<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<h2>\u00c9tape 1<\/h2>\n<p><span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span>\u00a0&#8211; Ouvrons le projet de\u00a0<a href=\"https:\/\/docs.google.com\/uc?export=download&amp;id=0Bxk2a0khnQQ7dG5HRVVRaWVYU1k\">d\u00e9part<\/a>\u00a0et testons l&rsquo;app.<br \/>\n<iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"http:\/\/www.youtube.com\/embed\/GA8a_7hRnmE?feature=oembed\" frameborder=\"0\" allowfullscreen><\/iframe><br \/>\nRemarquons que les modifications, ainsi que l\u00a0\u00bbajout d&rsquo;une nouvelle t\u00e2che, ne sont pas enregistr\u00e9s.<br \/>\n&nbsp;<\/p>\n<h2>\u00c9tape 1.1<\/h2>\n<p><span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; Analysons le sch\u00e9ma de d\u00e9part:<br \/>\n<a href=\"\/xcode\/wp-content\/uploads\/2013\/11\/Post-TIM_-_projet_de_depart-schema1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-648\" alt=\"Post-TIM_-_projet_de_depart-schema\" src=\"\/xcode\/wp-content\/uploads\/2013\/11\/Post-TIM_-_projet_de_depart-schema1.png\" width=\"1697\" height=\"680\" \/><\/a><\/p>\n<h2>\u00c9tape 1.2 &#8211; Activer la suppression des UITableViewCell sur &lsquo;swap&rsquo;.<\/h2>\n<p>La d\u00e9l\u00e9gation du UITableView propose la m\u00e9thode &lsquo;commitEditingStyle&rsquo; qui permet d&rsquo;activer la suppression d&rsquo;une cellule sur glissement horizontal.<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; Ajoutons la m\u00e9thode suivante \u00e0 la classe &lsquo;VCNotes.m&rsquo;<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/ *********************************************************************************\n\/\/ \u00c0 compl\u00e9ter\n\/\/ ETAPE 1.2 -  Ajouter la m\u00e9thode 'commitEditingStyle'\n\/\/              Actualiser le tableau des t\u00e2ches\n\/\/              Actualiser le UITableView\n\/\/              Enregistrer le tableau des t\u00e2ches dans 'listeDesTaches.plist'\n\/\/ ---------------------------------------------------------------------------------\n\/\/ M\u00e9thode de d\u00e9l\u00e9gation pour g\u00e9rer la suppression de la cellule sur swap\n\/\/ #################################################################################\n- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath\n\/\/ #################################################################################\n{\n    if (editingStyle == UITableViewCellEditingStyleDelete) {\n        \/\/ Effacer, de tableauDesTaches,\n        \/\/ l'\u00e9l\u00e9ment correspondant \u00e0 la cellule courante\n        [tableauDesTaches removeObjectAtIndex:indexPath.row];\n        \/\/ Enregistrer le tableau dans le fichier.plist\n        \/\/ atomically:YES = enregistrer dans une copie avant de remplacer le fichier original.\n        [tableauDesTaches writeToFile:[[NSBundle mainBundle] pathForResource:@\"listeDesTaches\" ofType:@\"plist\" ]atomically:YES];\n        \/\/ Actualiser le UITableView\n        [self.tableView reloadData];\n    } \/\/ FIN -&gt; editingStyle == delete\n} \/\/ ### FIN -&gt; commitEditingStyle\n\/\/ ---------------------------------------------------------------------------------<\/pre>\n<h2><\/h2>\n<p><span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; Testons le &lsquo;swap&rsquo; sur une des cellules du UITableView:<br \/>\n&nbsp;<br \/>\n<a href=\"\/xcode\/wp-content\/uploads\/2013\/11\/PostTIM-delete.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-658\" alt=\"PostTIM-delete\" src=\"\/xcode\/wp-content\/uploads\/2013\/11\/PostTIM-delete.png\" width=\"457\" height=\"412\" \/><\/a><br \/>\n&nbsp;<br \/>\n&nbsp;<\/p>\n<h2>\u00c9tape 1.3 &#8211;\u00a0Utiliser un &lsquo;NSDateFormatter&rsquo;\u00a0pour afficher une date en heure locale&#8230;<\/h2>\n<p>Si nous ex\u00e9cutons l&rsquo;application, nous allons remarquer que l&rsquo;heure affich\u00e9e des t\u00e2ches ne correspond pas aux donn\u00e9es du fichier &lsquo;listeDesTaches.plist&rsquo;. \u00a0Cel\u00e0 s&rsquo;explique par le fait qu&rsquo;un NSDate est localis\u00e9 au fuseau horaire &lsquo;UCT&rsquo; lors de sa conversion vers un NSString.<br \/>\n<a href=\"\/xcode\/wp-content\/uploads\/2013\/11\/POSTTIM-date-UCT.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-655\" alt=\"POSTTIM-date-UCT\" src=\"\/xcode\/wp-content\/uploads\/2013\/11\/POSTTIM-date-UCT.png\" width=\"844\" height=\"385\" \/><\/a><br \/>\nL&rsquo;utilisation de la classe &lsquo;NSDataFormatter&rsquo; va permettre d&rsquo;utiliser le fuseau horaire de l&rsquo;appareil lors de la conversion. \u00a0De plus, il sera possible de programmer les \u00e9l\u00e9ments de date \u00e0 afficher. \u00a0Par exemple, le nom du jour (lundi) + le num\u00e9ro du mois + HH:MM, &#8230;<br \/>\n<strong>Voir le site <a href=\"http:\/\/userguide.icu-project.org\/formatparse\/datetime\">suivant<\/a> pour les commandes de formatage d&rsquo;une date.<\/strong><br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; \u00a0Ajoutons le code suivant \u00e0 la m\u00e9thode &lsquo;cellForRowAtIndexPath&rsquo; du fichier &lsquo;VCNotes.m&rsquo;<\/p>\n<pre class=\"toolbar:1 lang:default mark:6-9,11 decode:true\">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n...\n     \/\/ ETAPE 1.3 - Utiliser un NSDateFormatter pour convertir en format local\n    \/\/ ---------------------------------------------------------------------------------\n    NSDateFormatter *unFormateurDeDate = [[NSDateFormatter alloc] init];\n    [unFormateurDeDate setDateFormat:@\"yyyy.MM.dd HH:mm\"];\n    NSString *dateMiseEnForme = [unFormateurDeDate stringFromDate:tacheCourante.date];\n    cell.date.text = dateMiseEnForme;\n    \/\/ ---------------------------------------------------------------------------------\n    \/\/ cell.date.text = tacheCourante.date.description;  \/\/ &lt;-  Ins\u00e9rer \/\/ devant\n...\n} \/\/ ### FIN -&gt; cellForRowAtIndexPath<\/pre>\n<p>&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; Testons l&rsquo;application et observons maintenant le format des dates.<br \/>\n<a href=\"\/xcode\/wp-content\/uploads\/2013\/11\/POSTTIM-date-locale.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-659\" alt=\"POSTTIM-date-locale\" src=\"\/xcode\/wp-content\/uploads\/2013\/11\/POSTTIM-date-locale.png\" width=\"971\" height=\"369\" \/><\/a><br \/>\n&nbsp;<br \/>\nEtape 1.4 &#8211; D\u00e9terminer la cellule qui a d\u00e9clench\u00e9 le &lsquo;segue&rsquo;<br \/>\nExplications &#8230;<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong> <\/span>&#8211; Ajoutons le code suivant \u00e0 la m\u00e9thode &lsquo;prepareForSegue&rsquo; du fichier &lsquo;VCNotes.m&rsquo;.<\/p>\n<pre class=\"toolbar:1 lang:default mark:10-12 decode:true\">\/\/  VCNotes.m\n-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender\n{\n    VCAjouterTache * vers = [segue destinationViewController];\n    \/\/ ETAPE 1.4 - D\u00e9terminer la cellule du sender\n    \/\/ ---------------------------------------------------------------------------------\n    \/\/ Note sender == UIButton et non pas UITableViewCell\n    \/\/ Donc, voici comment obtenir la position du UITableViewCell:\n    UIButton *button = (UIButton *)sender;\n    CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];\n    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];\n    \/\/ ---------------------------------------------------------------------------------<\/pre>\n<p>&nbsp;<br \/>\nEtape 1.5 \u00a0&#8211; D\u00e9terminer la destination du &lsquo;segue&rsquo; &#8211; 3 choix possibles<br \/>\nExplications&#8230;<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong>\u00a0<\/span>&#8211; Ajoutons le code suivant \u00e0 la m\u00e9thode &lsquo;prepareForSegue&rsquo; du fichier &lsquo;VCNotes.m&rsquo;.<\/p>\n<pre class=\"toolbar:1 lang:default mark:13-35 decode:true\">\/\/  VCNotes.m\n-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender\n{\n    VCAjouterTache * vers = [segue destinationViewController];\n...\n    \/\/ *********************************************************************************\n    \/\/ \u00c0 compl\u00e9ter\n    \/\/ ETAPE 1.5 -  D\u00e9terminer la destination du segue.\n    \/\/           -  Pr\u00e9parer les donn\u00e9es en fn de la destination\n    \/\/ ---------------------------------------------------------------------------------\n    \/\/ Tester si 'segue' est = 'ajouter'\n    if ([segue.identifier isEqual:@\"ajouter\"]){\n        \/\/ ETAPE 3.4b - Renseigner le d\u00e9l\u00e9gu\u00e9\n        \/\/ ...\n        vers.modeAjouter = YES;\n        NSLog(@\"Transition vers %@\", segue.identifier);\n    }\n    \/\/ Tester si 'segue' est = 'modifier'\n    if ([segue.identifier isEqual:@\"modifier\"]){\n        \/\/ ETAPE 3.5b - Renseigner le d\u00e9l\u00e9gu\u00e9\n        \/\/ ..\n        vers.modeAjouter = NO;\n        vers.detailTache = [[Tache alloc]initWithTache: tableauDesTaches[indexPath.row]];\n        \/\/ sauvegarder la s\u00e9lection courante pour le retour de modifierTache\n        indiceTacheCourante = indexPath.row;\n        NSLog(@\"Transition vers %@ avec indice: %d\", segue.identifier, indexPath.row);\n    }\n    \/\/ Tester si 'segue' est = 'detail'\n    if ([segue.identifier isEqual:@\"detail\"]){\n        vers.detailTache = [[Tache alloc]initWithTache: tableauDesTaches[indexPath.row]];\n        NSLog(@\"Transition vers %@ avec indice: %d\", segue.identifier, indexPath.row);\n    }\n    \/\/ ---------------------------------------------------------------------------------\n} \/\/ ### FIN -&gt; prepareForSegue<\/pre>\n<p>&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong><\/span> &#8211; Testons l&rsquo;application<br \/>\n<iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"http:\/\/www.youtube.com\/embed\/m89nz1KSrFg?feature=oembed\" frameborder=\"0\" allowfullscreen><\/iframe><br \/>\n<a href=\"https:\/\/docs.google.com\/uc?export=download&amp;id=0Bxk2a0khnQQ7WmZKMERZTDJydWs\">T\u00e9l\u00e9charger<\/a> le projet \u00e0 la fin de l&rsquo;\u00e9tape 1<br \/>\n&nbsp;<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<h1>\u00c9tape 2 \u00a0&#8211; Programmer un protocole O.C<\/h1>\n<p>Explications &#8230;<br \/>\n<span style=\"color: #ff0000;\"><strong>Note<\/strong><\/span>: \u00c9tape 2 est r\u00e9alis\u00e9e dans la classe &lsquo;VCAjouterTache&rsquo;.<\/p>\n<h2>\u00c9tape 2.1a et 2.1b &#8211; Programmation du protocole &lsquo;tacheDelegate&rsquo;<\/h2>\n<p><span style=\"color: #ff0000;\"><strong>ACTION<\/strong> <\/span>&#8211; Ajoutons le code suivant au fichier \u00a0&lsquo;VCAjouterTache&rsquo;.<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/  VCAjouterTache.h\n\/\/ ETAPE 2.1a - Programmer un protocole et la signature de ses m\u00e9thodes\n@protocol tacheDelegate &lt;NSObject&gt;\n@optional\n-(void) ajouterTache:(Tache*) detailInfo;\n-(void) modifierTache:(Tache*) detailInfo;\n@end\n\/\/ ---------------------------------------------------------------------------------\n@interface VCAjouterTache : UIViewController\n\/\/ *********************************************************************************\n\/\/ \u00c0 compl\u00e9ter\n\/\/ ETAPE 2.1b - D\u00e9finir une propri\u00e9t\u00e9 pour recevoir l'adresse du d\u00e9l\u00e9gu\u00e9\n\/\/ ---------------------------------------------------------------------------------\n@property id delegate;\n\/\/ ---------------------------------------------------------------------------------<\/pre>\n<p>&nbsp;<\/p>\n<h2>\u00c9tape 2.2 &#8211; Programmer l&rsquo;appel des m\u00e9thodes d&rsquo;un protocole<\/h2>\n<p>L&rsquo;appel d&rsquo;une m\u00e9thode d&rsquo;un protocole se fait suite \u00e0 un test sur [self.delegate respondsToSelector:@selector(uneM\u00e9thodeDuProtocole)]. \u00a0Cela permet de v\u00e9rifier s&rsquo;il existe un d\u00e9l\u00e9gu\u00e9 et si ce dernier a impl\u00e9ment\u00e9 la m\u00e9thode en question. \u00a0Si c&rsquo;est le cas alors l&rsquo;appel de la m\u00e9thode est lanc\u00e9 en utilisant la r\u00e9f\u00e9rence au d\u00e9l\u00e9gu\u00e9 (self.delegate).<br \/>\n&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>ACTION<\/strong>\u00a0<\/span>&#8211; Ajoutons le code suivant au fichier \u00a0&lsquo;VCAjouterTache&rsquo;.<br \/>\n&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/  VCAjouterTache.m\n- (IBAction)sauvegarder:(id)sender {\n    NSLog(@\"sauvegarder\");\n...\n    \/\/ ETAPE 2.2 -  Si il y a un d\u00e9l\u00e9gu\u00e9 alors lancer les m\u00e9thodes de d\u00e9l\u00e9gation\n    \/\/              ajouterTache et modifierTache.\n    \/\/ ---------------------------------------------------------------------------------\n    \/\/ Si en modeAjouter\n    if (self.modeAjouter) {\n        if ([self.delegate respondsToSelector:@selector(ajouterTache:)]){\n            NSLog(@\"Le d\u00e9l\u00e9gu\u00e9 r\u00e9pond \u00e0 ajouterTache...\");\n            [self.delegate ajouterTache:info];\n        } \/\/ selector-ajouterTache\n    }  \/\/ modeAjouter\n    else \/\/ Si modeModifier\n    {\n        if ([self.delegate respondsToSelector:@selector(modifierTache:)]){\n            NSLog(@\"Le d\u00e9l\u00e9gu\u00e9 r\u00e9pond \u00e0 modifierTache...\");\n            [self.delegate modifierTache:info];\n        } \/\/ selector-modifierTache\n    }  \/\/ modeModifier\n    \/\/ ---------------------------------------------------------------------------------\n ...\n}  \/\/ sauvegarder<\/pre>\n<p>Le protocole de la classe &lsquo;VCAjouterTache&rsquo; est maintenant en place. \u00a0Par contre, il n&rsquo;y a pas de d\u00e9l\u00e9gu\u00e9 \u00e0 cette \u00e9tape ci. \u00a0Donc, si nous testons le bouton &lsquo;modifier&rsquo; de la premi\u00e8re cellule suivi du bouton &lsquo;enregistrer&rsquo; nous allons remarquer l&rsquo;absence du message &lsquo;NSLog(@\u00a0\u00bbLe d\u00e9l\u00e9gu\u00e9 r\u00e9pond \u00e0 modifierTache&#8230;\u00a0\u00bb);&rsquo;.<br \/>\nIl nous reste \u00e0 souscrire au protocole &lt;tacheDelegate&gt; \u00e0 partir de la classe &lsquo;VCNotes&rsquo;.<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<h2>\u00c9tape 3.3 &#8211; Souscrire au protocole\u00a0&lt;tacheDelegate&gt;.<\/h2>\n<p><span style=\"color: #ff0000;\"><strong>Note<\/strong><\/span>: La num\u00e9rotation passe \u00e0 3.x car les \u00e9tapes suivantes sont r\u00e9alis\u00e9es dans la classe &lsquo;VCNotes&rsquo;.<br \/>\nPour souscrire \u00e0 un ou plusieurs protocole dans une classe il faut:<\/p>\n<ol>\n<li>\u00c9num\u00e9rer les protocoles entre &lt;p1,p2, &#8230;&gt; au bout de la ligne @interface du fichier.m de la classe.<\/li>\n<li>Placer l&rsquo;adresse (self) de la classe dans la propri\u00e9t\u00e9 &lsquo;delegate&rsquo; de la classe qui propose le protocole.<\/li>\n<\/ol>\n<p><strong>Note<\/strong>: Le point deux(2) sera r\u00e9alis\u00e9 \u00e0 3.4b.<br \/>\n<strong>Note<\/strong>: Il faut proc\u00e9der ainsi pour les classes qui ne sont pas dans la librairie des objets en mode GUI sous Xcode. \u00a0Dans ce cas, il n&rsquo;est pas possible de tracer un lien entre la propri\u00e9t\u00e9 &lsquo;delegate&rsquo; et l&rsquo;icon de la classe d&rsquo;une sc\u00e8ne du projet.<br \/>\n<span style=\"color: #ff0000;\"><b>ACTION<\/b><\/span>&#8211; Ajoutons le code suivant au fichier &lsquo;VCNotes.m&rsquo;<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/ VCNotes.m\n\/\/ ETAPE 3.3 -  Indiquer que la classe courante doit souscrire au protocole de la\n\/\/              classe 'VCAjouterTache' -&gt;  '&lt;tacheDelegate&gt;'\n\/\/ ---------------------------------------------------------------------------------\n@interface VCNotes () &lt;tacheDelegate&gt; \/\/ &lt; ** ici ** &gt;\n@end<\/pre>\n<p>\u00c0 partir de cette \u00e9tape, il est maintenant possible de programmer les m\u00e9thodes de d\u00e9l\u00e9gation &lsquo;ajouterTache&rsquo; et &lsquo;modifierTache&rsquo; du protocole &lsquo;tacheDelegate&rsquo; de la classe &lsquo;VC&rsquo;.<br \/>\nNote: \u00a0\u00c9tant donn\u00e9 que les m\u00e9thodes de d\u00e9l\u00e9gation \u00e9taient dans un bloc &lsquo;@optional&rsquo;\u00a0nous ne sommes pas oblig\u00e9 de les programmer.<br \/>\nCommen\u00e7ons par programmer la m\u00e9thode &lsquo;ajouterTache&rsquo;<br \/>\n&nbsp;<\/p>\n<h2>\u00c9tape 3.4a &#8211; Programmation de la m\u00e9thode &lsquo;ajouterTache&rsquo;<\/h2>\n<p><span style=\"color: #ff0000;\"><b><br \/>\nACTION<\/b><\/span><span style=\"font-size: 13px;\">&#8211; Ajoutons le code suivant au fichier &lsquo;VCNotes.m&rsquo;<\/span><br \/>\n&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/  VCNotes.m\n\/\/ ETAPE 3.4 - Programmer la m\u00e9thode de d\u00e9l\u00e9gation 'ajouterTache'\n\/\/ ---------------------------------------------------------------------------------\n-(void) ajouterTache:(Tache*)info{\n    NSLog(@\"d\u00e9l\u00e9gation - ajouterTache, info = %@\", info);\n    \/\/ Ajouter au tableauTaches les donn\u00e9es re\u00e7ues.\n    [tableauDesTaches addObject:[info tacheToDictionary]];\n    NSLog(@\"tableauDesTaches ajouterTache = %@\", tableauDesTaches);\n    \/\/ Actualiser le UITableView\n    [self.tableView reloadData];\n    \/\/ Enregistrer tableauTaches dans le fichier 'listeDesTaches.plist'\n    \/\/ atomically:YES = enregistrer dans une copie avant de remplacer le fichier original.\n    [tableauDesTaches writeToFile:[[NSBundle mainBundle] pathForResource:@\"listeDesTaches\" ofType:@\"plist\" ]atomically:YES];\n} \/\/ ### FIN -&gt; ajouterTache<\/pre>\n<h2><\/h2>\n<h2>\u00c9tape 3.4b &#8211; Renseigner la propri\u00e9t\u00e9 &lsquo;delegate&rsquo; pour la destination &lsquo;ajouter&rsquo;.<\/h2>\n<p><b><br \/>\n<span style=\"color: #ff0000;\">ACTION<\/span><\/b>&#8211; Ajoutons le code suivant au fichier &lsquo;VCNotes.m&rsquo;<br \/>\n&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:default mark:9 decode:true\">\/\/  VCNotes.m\n-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender\n    \/\/ Tester si 'segue' est = 'ajouter'\n    if ([segue.identifier isEqual:@\"ajouter\"]){\n        \/\/ *********************************************************************************\n        \/\/ \u00c0 compl\u00e9ter\n        \/\/ ETAPE 3.4b - Renseigner le d\u00e9l\u00e9gu\u00e9\n        \/\/ ---------------------------------------------------------------------------------\n        vers.delegate = self;\n        \/\/ ---------------------------------------------------------------------------------\n...\n    }<\/pre>\n<p><span style=\"color: #ff0000;\"><strong><br \/>\nACTION<\/strong><\/span> &#8211; Testons l&rsquo;application<br \/>\n<iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"http:\/\/www.youtube.com\/embed\/TGp11r63QMk?feature=oembed\" frameborder=\"0\" allowfullscreen><\/iframe><br \/>\nNote: Vous remarquerez, \u00e0 la fin de la vid\u00e9o, \u00a0que la modification d&rsquo;une t\u00e2che n&rsquo;entraine pas l&rsquo;appel de la m\u00e9thode &lsquo;modifierTache&rsquo; car elle n&rsquo;est pas impl\u00e9ment\u00e9e dans la classe &lsquo;VCDetails&rsquo;.<br \/>\n&nbsp;<\/p>\n<h2>\u00c9tape 3.5a &#8211; Programmation de la m\u00e9thode &lsquo;ajouterTache&rsquo;<\/h2>\n<p><b><br \/>\n<span style=\"color: #ff0000;\">ACTION<\/span><\/b>&#8211; Ajoutons le code suivant au fichier &lsquo;VCNotes.m&rsquo;<br \/>\n&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">\/\/ VCNotes.m\n\/\/ ETAPE 3.5a - Programmer la m\u00e9thode de d\u00e9l\u00e9gation 'ModifierTache'\n\/\/ ---------------------------------------------------------------------------------\n-(void) modifierTache:(Tache*)info{\n    NSLog(@\"retour de la m\u00e9thode 'modifier', info = %@\", info);\n    \/\/ Remplacer l'\u00e9l\u00e9ment courant du tableauTaches par les donn\u00e9es re\u00e7ues.\n    tableauDesTaches[indiceTacheCourante] = [info tacheToDictionary];\n    NSLog(@\"tableauDesTaches \u00e9l\u00e9ment %d modifi\u00e9 = %@\", indiceTacheCourante, tableauDesTaches);\n    \/\/ Actualiser le UITableView\n    [self.tableView reloadData];\n    \/\/ Enregistrer tableauTaches dans le fichier 'listeDesTaches.plist'\n    [tableauDesTaches writeToFile:[[NSBundle mainBundle] pathForResource:@\"listeDesTaches\" ofType:@\"plist\" ]atomically:YES];\n} \/\/ ### FIN -&gt; modifierTache\n\/\/ ---------------------------------------------------------------------------------<\/pre>\n<p>&nbsp;<\/p>\n<h2>\u00c9tape 3.5b &#8211; Renseigner la propri\u00e9t\u00e9 &lsquo;delegate&rsquo; pour la destination &lsquo;modifier&rsquo;.<\/h2>\n<p><span style=\"color: #ff0000;\"><b><br \/>\nACTION<\/b><\/span>&#8211; Ajoutons le code suivant au fichier &lsquo;VCNotes.m&rsquo;<br \/>\n&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:default mark:7 decode:true\">\/\/  VCNotes.m\n-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender\n    \/\/ Tester si 'segue' est = 'modifier'\n    if ([segue.identifier isEqual:@\"modifier\"]){\n        \/\/ ETAPE 3.5b - Renseigner le d\u00e9l\u00e9gu\u00e9\n        \/\/ ---------------------------------------------------------------------------------\n        vers.delegate = self;\n        \/\/ ---------------------------------------------------------------------------------<\/pre>\n<p>&nbsp;<br \/>\n<strong><span style=\"color: #ff0000;\">ACTION<\/span> <\/strong>&#8211; Testons l&rsquo;application finale!<br \/>\nVoil\u00e0 ce qui compl\u00e8te le laboratoire Post&rsquo;TIM!<br \/>\n<a href=\"https:\/\/docs.google.com\/uc?export=download&amp;id=0Bxk2a0khnQQ7UW5MWTVkNlI3NzA\">T\u00e9l\u00e9charger<\/a> le projet termin\u00e9.<br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mise en place d&rsquo;un protocole O.C Note: document en cours de r\u00e9vision. Contenu Programmer un protocole O.C. Programmer l&rsquo;appel de m\u00e9thodes de d\u00e9l\u00e9gation sur &lsquo;respondToSelector&rsquo;. Enregistrer un NSArray dans un fichier de propri\u00e9t\u00e9s (.plist). Utiliser un formateur de date pour afficher un NSDate en heure locale. Programmer plusieurs destinations dans la m\u00e9thode &lsquo;prepareForSegue&rsquo; Pr\u00e9-requis: Avoir [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":26,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-617","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages\/617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/comments?post=617"}],"version-history":[{"count":0,"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages\/617\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages\/26"}],"wp:attachment":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/media?parent=617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}