{"id":117,"date":"2016-02-27T00:14:12","date_gmt":"2016-02-27T00:14:12","guid":{"rendered":"https:\/\/www.aya.io\/ayablog\/?p=117"},"modified":"2022-02-07T02:38:23","modified_gmt":"2022-02-07T02:38:23","slug":"qu-est-ce-qu-un-delegate","status":"publish","type":"post","link":"https:\/\/www.aya.io\/blog\/qu-est-ce-qu-un-delegate\/","title":{"rendered":"Qu&rsquo;est-ce qu&rsquo;un \u00ab\u00a0delegate\u00a0\u00bb ?"},"content":{"rendered":"<p>Qu'est-ce qu'un &quot;delegate&quot; ?<\/p>\n<p>On retrouve le principe de la d\u00e9l\u00e9gation partout dans OS X et iOS.<\/p>\n<p>Un champ de texte, par exemple, pr\u00e9vient son potentiel d\u00e9l\u00e9gu\u00e9 que l'utilisateur est en train de taper du texte, a fini de taper, etc.<\/p>\n<p>Ceci dit, est-il utile d'impl\u00e9menter nous-m\u00eame la d\u00e9l\u00e9gation dans nos objets ? Et comment fait-on ?<\/p>\n<p>On va s'amuser \u00e0 explorer quelques exemples, purement en Swift, rapidement, dans un simple Playground.<\/p>\n<p><!-- more --><\/p>\n<h1>Principe<\/h1>\n<p>La d\u00e9l\u00e9gation n\u00e9c\u00e9ssite : un protocole, un d\u00e9l\u00e9gateur, un d\u00e9l\u00e9gu\u00e9.<\/p>\n<h2>Protocole<\/h2>\n<p>Deux objets vont pouvoir communiquer gr\u00e2ce \u00e0 un protocole.<\/p>\n<p>Ce protocole d\u00e9finit quelles sont les m\u00e9thodes et propri\u00e9t\u00e9s qui seront utilisables par les objets qui se conformeront au protocole.<\/p>\n<p>On peut dire que dans ce contexte, un protocole est comme un contrat entre deux parties, d\u00e9finissante les r\u00f4les et responsabilit\u00e9s de ceux qui le signent.<\/p>\n<h2>D\u00e9l\u00e9gateur<\/h2>\n<p>Le d\u00e9l\u00e9gateur est l'objet qui <em>contient une variable<\/em> souvent nomm\u00e9e par convention &quot;delegate&quot;.<\/p>\n<p>Cette variable est du type du protocole - mais optionnel, car le d\u00e9l\u00e9gateur peut tr\u00e8s bien ne pas avoir de d\u00e9l\u00e9gu\u00e9 \u00e0 un moment donn\u00e9.<\/p>\n<p>Le d\u00e9l\u00e9gateur d\u00e9pend donc d'une instance de l'objet qui servira de d\u00e9l\u00e9gu\u00e9.<\/p>\n<h2>D\u00e9l\u00e9gu\u00e9<\/h2>\n<p>Le d\u00e9l\u00e9gu\u00e9 est l'objet qui se <em>conforme au protocole<\/em>.<\/p>\n<p>Le d\u00e9l\u00e9gu\u00e9 est donc celui qui doit impl\u00e9menter les m\u00e9thodes\/propri\u00e9t\u00e9s exig\u00e9es par le protocole.<\/p>\n<h1>Du concret<\/h1>\n<p>Nous allons utiliser deux exemples.<\/p>\n<p>D'abord, une tr\u00e8s simple illustration du principe, qui va donner une id\u00e9e g\u00e9n\u00e9rale.<\/p>\n<p>Ensuite, une impl\u00e9mentation beaucoup plus int\u00e9ressante mais forc\u00e9ment un peu moins lisible au premier abord.<\/p>\n<h1>Exemple 1<\/h1>\n<p>Disons qu'on a un objet g\u00e9n\u00e8re r\u00e9guli\u00e8rement des \u00e9v\u00e8nements, dans notre exemple une simple classe qui cr\u00e9\u00e9 des num\u00e9ros de code.<\/p>\n<p>Pour respecter le principe de responsabilit\u00e9 unique, cette classe ne fait que g\u00e9n\u00e9rer les codes, elle ne les affiche pas.<\/p>\n<p>A la place, elle <em>d\u00e9l\u00e8gue<\/em> la t\u00e2che d'afficher le r\u00e9sultat \u00e0 d'autres objets - \u00e0 condition que ces objets soient conformes au protocole exig\u00e9 par le g\u00e9n\u00e9rateur.<\/p>\n<h2>Le protocole<\/h2>\n<p>On va faire simple, le protocole exigera uniquement d'impl\u00e9menter une m\u00e9thode <code>anEventHappened(code: Int)<\/code> (&quot;quelque chose est arriv\u00e9&quot;), que le d\u00e9l\u00e9gu\u00e9 pourra invoquer une fois son travail achev\u00e9 :<\/p>\n<pre><code class=\"language-swift\">protocol ListensToEvents {\n\n    func anEventHappened(code: Int)\n\n}<\/code><\/pre>\n<p>Comme c'est un protocole, il n'y a pas d'impl\u00e9mentation, seulement une d\u00e9claration. <\/p>\n<p>L'impl\u00e9mentation est de la responsabilit\u00e9 de l'objet qui se conforme au protocole.<\/p>\n<p>Le protocole est nomm\u00e9 <code>ListensToEvents<\/code> car il est utilis\u00e9 par des objets qui \u00e9coutent des messages\/\u00e9v\u00e9nements.<\/p>\n<p>Par convention, on nomme un protocole en restant dans le champ lexical de la responsabilit\u00e9 : &quot;SomethingCompatible&quot;, &quot;SomethingConvertible&quot;, etc, ou de l'activit\u00e9 : &quot;IsAbleToDispatch&quot;, &quot;ManagesRemovableStuff&quot;, etc.<\/p>\n<h2>Le d\u00e9l\u00e9gu\u00e9<\/h2>\n<p>Le but \u00e9tant de d\u00e9coupler la g\u00e9n\u00e9ration des codes de l'affichage des codes, notre d\u00e9l\u00e9gu\u00e9 sera donc ici une &quot;imprimante&quot;.<\/p>\n<p>Le g\u00e9n\u00e9rateur g\u00e9n\u00e8re, et dit \u00e0 son d\u00e9l\u00e9gu\u00e9 : &quot;j'ai g\u00e9n\u00e9r\u00e9, tu peux afficher&quot;, et le d\u00e9l\u00e9gu\u00e9 affiche - ou pas.<\/p>\n<p>Par exemple :<\/p>\n<pre><code class=\"language-swift\">class ClassicPrinter: ListensToEvents {\n\n    func anEventHappened(code: Int) {\n        print(&quot;CODE: \\(code)&quot;)\n    }\n\n}<\/code><\/pre>\n<p>Notre imprimante, la classe <code>ClassicPrinter<\/code>, se conforme au protocole et l'impl\u00e9mente. Elle affiche simplement le code.<\/p>\n<p>Autre exemple :<\/p>\n<pre><code class=\"language-swift\">class FancyPrinter: ListensToEvents {\n\n    func anEventHappened(code: Int) {\n        print(&quot;\\(NSDate()) - GENERATED CODE: \\(code)&quot;)\n    }\n\n}<\/code><\/pre>\n<p>Cet autre objet, qui se conforme aussi au m\u00eame protocole, impl\u00e9mente donc la m\u00eame m\u00e9thode, mais diff\u00e9remment - elle affiche aussi la date.<\/p>\n<p>Ces deux objets vont servir de d\u00e9l\u00e9gu\u00e9 chacun leur tour dans notre d\u00e9mo.<\/p>\n<h2>Le d\u00e9l\u00e9gateur<\/h2>\n<p>Une petite classe qui g\u00e9n\u00e8re des codes et qui pr\u00e9vient le d\u00e9l\u00e9gu\u00e9 \u00e0 chaque code g\u00e9n\u00e9r\u00e9.<\/p>\n<pre><code class=\"language-swift\">class EventsGenerator {\n\n    var delegate: ListensToEvents?\n\n    var codes = [Int]()\n\n    func generateNewCode() {\n        codes.append(Int(arc4random_uniform(1_000_000)))\n\n        if let printer = delegate {\n            printer.anEventHappened(codes.last!)\n        } else {\n            \/\/ No delegate, the code stays secret...\n        }\n    }\n\n}<\/code><\/pre>\n<p>Le d\u00e9l\u00e9gateur contient une variable du type du protocole, c'est cette variable qui sert de r\u00e9f\u00e9rence vers le\/les d\u00e9l\u00e9gu\u00e9(s).<\/p>\n<h2>Let's go<\/h2>\n<p>On colle tout \u00e7a dans un Playground :<\/p>\n<pre><code class=\"language-swift\">protocol ListensToEvents {\n    func anEventHappened(code: Int)\n}\n\nclass ClassicPrinter: ListensToEvents {\n    func anEventHappened(code: Int) {\n        print(&quot;CODE: \\(code)&quot;)\n    }\n}\n\nclass FancyPrinter: ListensToEvents {\n    func anEventHappened(code: Int) {\n        print(&quot;\\(NSDate()) - GENERATED CODE: \\(code)&quot;)\n    }\n}\n\nclass EventsGenerator {\n    var delegate: ListensToEvents?\n\n    var codes = [Int]()\n\n    func generateNewCode() {\n        codes.append(Int(arc4random_uniform(1_000_000)))\n        if let printer = delegate {\n            printer.anEventHappened(codes.last!)\n        } else {\n            \/\/ No delegate, the code stays secret...\n        }\n    }\n}<\/code><\/pre>\n<p>Et pour faire fonctionner le tout, nous cr\u00e9ons un g\u00e9n\u00e9rateur :<\/p>\n<pre><code class=\"language-swift\">let generator = EventsGenerator()<\/code><\/pre>\n<p>Maintenant, que se passe-t-il si l'on invoque la g\u00e9n\u00e9ration d'un code ?<\/p>\n<pre><code class=\"language-swift\">generator.generateNewCode()<\/code><\/pre>\n<p>On ne voit rien dans la console. Pourtant, nous savons que le code a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9. Mais le g\u00e9n\u00e9rateur n'a pas encore d'imprimante d\u00e9l\u00e9gu\u00e9e, donc rien n'est imprim\u00e9.<\/p>\n<p>Maintenant, offrons un d\u00e9l\u00e9gu\u00e9 \u00e0 notre g\u00e9n\u00e9rateur, et invoquons \u00e0 nouveau la cr\u00e9ation d'un code&nbsp;:<\/p>\n<pre><code class=\"language-swift\">generator.delegate = ClassicPrinter()\ngenerator.generateNewCode()<\/code><\/pre>\n<p>Cette-fois ci nous voyons s'afficher :<\/p>\n<blockquote>\n<p>CODE: 423312<\/p>\n<\/blockquote>\n<p>Le g\u00e9n\u00e9rateur a effectu\u00e9 le m\u00eame travail, mais cette-fois ci son d\u00e9l\u00e9gu\u00e9 \u00e0 r\u00e9pondu son appel.<\/p>\n<p>Donnons-lui maintenant un nouveau d\u00e9l\u00e9gu\u00e9 :<\/p>\n<pre><code class=\"language-swift\">generator.delegate = FancyPrinter()\ngenerator.generateNewCode()<\/code><\/pre>\n<p>S'affiche donc logiquement :<\/p>\n<blockquote>\n<p>2016-02-27 16:18:54 +0000 - GENERATED CODE: 782392<\/p>\n<\/blockquote>\n<p>car l'imprimante a chang\u00e9.<\/p>\n<p>Et si on enl\u00e8ve le d\u00e9l\u00e9gu\u00e9 ?<\/p>\n<pre><code class=\"language-swift\">generator.delegate = nil\ngenerator.generateNewCode()<\/code><\/pre>\n<p>Plus rien ne s'affiche, car le g\u00e9n\u00e9rateur n'a plus d'imprimante d\u00e9l\u00e9gu\u00e9e.<\/p>\n<p>Mais nous pouvons v\u00e9rifier que les quatre invocations du g\u00e9n\u00e9rateur ont bien produit quatre codes :<\/p>\n<pre><code class=\"language-swift\">print(generator.codes)<\/code><\/pre>\n<blockquote>\n<p>[881982, 423312, 782392, 786518]<\/p>\n<\/blockquote>\n<p>Le premier \u00e9tait invisible, le deuxi\u00e8me \u00e9tait imprim\u00e9 par ClassicPrinter, le troisi\u00e8me par FancyPrinter, et le quatri\u00e8me de nouveau invisible.<\/p>\n<p><strong>En utilisant la d\u00e9l\u00e9gation, nous avons s\u00e9par\u00e9 les responsabilit\u00e9s entre les objets<\/strong>, qui peuvent donc effectuer leur travail sans \u00eatre d\u00e9pendants les uns des autres - ce que l'on recherche en permanence avec la programmation &quot;orient\u00e9e objet&quot;.<\/p>\n<p><em>Le code du Playground pour cet exemple est <a href=\"https:\/\/gist.github.com\/ericdke\/aa1ce0a3d38bed3291e3\">disponible dans ce Gist<\/a>.<\/em><\/p>\n<h1>Exemple 2<\/h1>\n<p>Un usage courant pour la d\u00e9l\u00e9gation est le passage de message, souvent lorsqu'une t\u00e2che vient d'\u00eatre accomplie.<\/p>\n<p>Dans cette partie du tuto nous allons cr\u00e9er une double d\u00e9l\u00e9gation : un canal de communication restreint entre objets en passant par deux protocoles, un pour d\u00e9l\u00e9gateur-&gt;d\u00e9l\u00e9gu\u00e9 et un pour d\u00e9l\u00e9gu\u00e9-&gt;d\u00e9l\u00e9gateur.<\/p>\n<p>On va raconter la petite histoire d'un chef de chantier qui va faire lancer deux \u00e9quipes sur une maison.<\/p>\n<p>Dans tous les cas, le chef donnera ses ordres et les \u00e9quipes concern\u00e9es effectueront le travail, mais tout ce qui est communication entre le chef et les \u00e9quipes va se faire via d\u00e9l\u00e9gation.<\/p>\n<h2>Protocoles<\/h2>\n<p>Un protocole qui devra \u00eatre adopt\u00e9 par les \u00e9quipes et qui sera utilis\u00e9 par le chef via sa variable <em>delegate<\/em>&nbsp;:<\/p>\n<pre><code class=\"language-swift\">protocol CanBuildHouses {\n\n    func startWorking()\n\n}<\/code><\/pre>\n<p>et celui qui sera adopt\u00e9 par le chef et sera utilis\u00e9 par les \u00e9quipes via leur variable <em>delegate<\/em>&nbsp;:<\/p>\n<pre><code class=\"language-swift\">protocol CanManageTeams {\n\n    func aTeamHasStartedWorking(team: Team)\n\n    func aTeamHasFinishedWorking(team: Team)\n\n}<\/code><\/pre>\n<h2>Le d\u00e9l\u00e9gateur<\/h2>\n<p>Le boss va avoir une m\u00e9thode <code>giveOrder<\/code> qui demandera aux d\u00e9l\u00e9gu\u00e9s d'invoquer leur propre m\u00e9thode <code>startWorking<\/code>.<\/p>\n<p>Dans <code>giveOrder<\/code> le boss va d'abord v\u00e9rifier qu'une \u00e9quipe est disponible en v\u00e9rifiant que la variable <code>delegate<\/code> ne soit pas <code>nil<\/code>.<\/p>\n<p>Comme cette variable repr\u00e9sente une \u00e9quipe employ\u00e9e par le boss, on va d'ailleurs la nommer <code>employee<\/code> (&quot;employ\u00e9&quot;).<\/p>\n<p>Et pour pouvoir recevoir les communications d'une \u00e9quipe, le boss doit impl\u00e9menter les deux m\u00e9thodes du protocole auquel il se conforme.<\/p>\n<p>En fonction du message re\u00e7u, le boss f\u00e9licitera ou pas l'\u00e9quipe.<\/p>\n<p>Voici le boss en entier :<\/p>\n<pre><code class=\"language-swift\">class Contractor: CanManageTeams {\n\n    var name: String\n\n    init(name: String) {\n        self.name = name\n    }\n\n    var employee: CanBuildHouses?\n\n    func giveOrders() {\n        guard let currentTeam = self.employee else {\n            print(&quot;\\(name): No new team in sight.\\n&quot;)\n            return\n        }\n\n        print(&quot;\\(name): Ah! Let&#039;s give some work to this team...\\n&quot;)\n\n        currentTeam.startWorking()\n    }\n\n    func aTeamHasStartedWorking(team: Team) {\n        print(&quot;\\(name): Ok \\(team.name), see you later today!\\n&quot;)\n    }\n\n    func aTeamHasFinishedWorking(team: Team) {\n        if team.taskDuration &lt; 7 {\n            print(&quot;\\(name): Congratulations, \\(team.name), work done in \\(team.taskDuration) seconds.\\n&quot;)\n        } else {\n            print(&quot;\\(name): Really, \\(team.name)? You can do better than \\(team.taskDuration) seconds.\\n&quot;)\n        }\n\n    }   \n}<\/code><\/pre>\n<h2>Le d\u00e9l\u00e9gu\u00e9<\/h2>\n<p>Notre \u00e9quipe sera capable de commencer \u00e0 travailler selon les ordres du boss en adoptant et en se conformant au protocole <code>CanBuildHouses<\/code> qui exige une m\u00e9thode <code>startWorking<\/code>.<\/p>\n<p>L'\u00e9quipe utilise \u00e9galement une variable <code>delegate<\/code> qui est un optionnel <code>CanManageTeams<\/code> et permettra de communiquer avec le chef qui aura adopt\u00e9 ce protocole.<\/p>\n<p>Comme cette variable ne sert qu'\u00e0 \u00e7a, nous la nommerons en fait <code>reportsTo<\/code> (&quot;reporte \u00e0&quot;).<\/p>\n<p>Et un simple nombre g\u00e9n\u00e9r\u00e9 au hasard servira pour cr\u00e9er une p\u00e9riode de &quot;travail&quot; pour l'\u00e9quipe.<\/p>\n<p>La classe \u00e9quipe :<\/p>\n<pre><code class=\"language-swift\">class Team: CanBuildHouses {\n\n    var name: String\n\n    var reportsTo: CanManageTeams?\n\n    var taskDuration:UInt32 = 0\n\n    init(name: String) {\n        self.name = name\n    }\n\n    func startWorking() {\n        if let announce = reportsTo {\n            print(&quot;\\(name): We&#039;re going to start in an instant, let&#039;s tell the boss...\\n&quot;)\n            announce.aTeamHasStartedWorking(self)\n        } else {\n            print(&quot;\\(name): No boss in sight, let&#039;s just start working.\\n&quot;)\n        }\n        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {\n            self.taskDuration = arc4random_uniform(10)+2\n            sleep(self.taskDuration) \/\/ &quot;working&quot; for some time\n            dispatch_async(dispatch_get_main_queue()) {\n                if let announce = self.reportsTo {\n                    print(&quot;\\(self.name): We&#039;re finished, let&#039;s tell the boss!\\n&quot;)\n                    announce.aTeamHasFinishedWorking(self)\n                } else {\n                    print(&quot;\\(self.name): We&#039;re finished! No boss in sight, let&#039;s just have a beer.\\n&quot;)\n                }\n\n            }\n        }\n    }\n\n}<\/code><\/pre>\n<h2>Let's go<\/h2>\n<p>On colle tout \u00e7a dans un Playground, et on cr\u00e9e nos objets, un employeur et deux \u00e9quipes :<\/p>\n<pre><code class=\"language-swift\">let boss = Contractor(name: &quot;BOSS&quot;)\nlet teamJohn = Team(name: &quot;JOHN&quot;)\nlet teamJane = Team(name: &quot;JANE&quot;)<\/code><\/pre>\n<p>Pour permetter aux \u00e9quipes de communiquer avec le boss, on le leur attribue comme d\u00e9l\u00e9gu\u00e9 :<\/p>\n<pre><code class=\"language-swift\">teamJohn.reportsTo = boss\nteamJane.reportsTo = boss<\/code><\/pre>\n<p>Bon, pour le moment le boss, lui, n'a pas encore de d\u00e9l\u00e9gu\u00e9(s).<\/p>\n<p>Que se passe-t-il s'il demande \u00e0 un d\u00e9l\u00e9gu\u00e9 de travailler ?<\/p>\n<pre><code class=\"language-swift\">boss.giveOrders()<\/code><\/pre>\n<p>Rien. Car sa variable <code>employee<\/code> est <code>nil<\/code>. Notre boss va alors s'exclamer qu'aucune \u00e9quipe n'est en vue.<\/p>\n<blockquote>\n<p>No new team in sight.<\/p>\n<\/blockquote>\n<p>Cr\u00e9ons maintenant une s\u00e9quence qui va mettre en valeur le r\u00f4le de la d\u00e9l\u00e9gation.<\/p>\n<p>Nous allons attribuer une \u00e9quipe au boss puis lancer le travail, puis recommencer avec l'autre \u00e9quipe - et pour finir nous allons enlever le d\u00e9l\u00e9gu\u00e9 du boss et demander quand m\u00eame de lancer le travail.<\/p>\n<pre><code class=\"language-swift\">boss.employee = teamJane\nboss.giveOrders()\n\nboss.employee = teamJohn\nboss.giveOrders()\n\nboss.employee = nil\nboss.giveOrders()<\/code><\/pre>\n<p>Et voici la s\u00e9quence qui va se d\u00e9rouler dans la console :<\/p>\n<blockquote>\n<p>BOSS: Ah! Let's give some work to this team...<\/p>\n<p>JANE: We're going to start in an instant, let's tell the boss...<\/p>\n<p>BOSS: Ok JANE, see you later today!<\/p>\n<p>BOSS: Ah! Let's give some work to this team...<\/p>\n<p>JOHN: We're going to start in an instant, let's tell the boss...<\/p>\n<p>BOSS: Ok JOHN, see you later today!<\/p>\n<p>BOSS: No new team in sight.<\/p>\n<p>JANE: We're finished, let's tell the boss!<\/p>\n<p>BOSS: Congratulations, JANE, work done in 2 seconds.<\/p>\n<p>JOHN: We're finished, let's tell the boss!<\/p>\n<p>BOSS: Really, JOHN? You can do better than 7 seconds.<\/p>\n<\/blockquote>\n<p>Maintenant, pour vraiment finir de tout comprendre, amusez-vous dans le Playground \u00e0 varier les s\u00e9quences : un seul employ\u00e9 pour le boss, deux \u00e9quipes mais une seule a un boss d\u00e9l\u00e9gu\u00e9, etc. Genre :<\/p>\n<pre><code class=\"language-swift\">teamJohn.reportsTo = boss\n\/\/ teamJane.reportsTo = boss\n\nboss.employee = teamJane\nboss.giveOrders()\n\nboss.employee = teamJohn\nboss.giveOrders()\n\nboss.employee = nil\nboss.giveOrders()<\/code><\/pre>\n<p>ou<\/p>\n<pre><code class=\"language-swift\">teamJohn.reportsTo = boss\nteamJane.reportsTo = boss\n\nboss.employee = teamJane\nboss.giveOrders()\n\n\/\/ boss.employee = teamJohn\nboss.giveOrders()\n\nboss.employee = nil\nboss.giveOrders()<\/code><\/pre>\n<p>etc.<\/p>\n<p>Et comme nous utilisons GCD, n'oubliez pas d'inclure ceci en haut du Playground :<\/p>\n<pre><code class=\"language-swift\">import XCPlayground\nXCPlaygroundPage.currentPage.needsIndefiniteExecution = true<\/code><\/pre>\n<p>pour autoriser l'ex\u00e9cution des background threads.<\/p>\n<p><em>Le code du Playground pour cet exemple est <a href=\"https:\/\/gist.github.com\/ericdke\/d8dfa7f01f1a52feaa7c\">disponible dans ce Gist<\/a>.<\/em><\/p>\n<h1>Conclusion<\/h1>\n<p>Tout ce qui peut \u00eatre fait par d\u00e9l\u00e9gation peut aussi \u00eatre effectu\u00e9 diff\u00e9remment.<\/p>\n<p>La d\u00e9l\u00e9gation n'est qu'un paradigme parmi d'autres - mais il a l'avantage d'offrir des avantages puissants sans s'encombrer de complexit\u00e9s particuli\u00e8res.<\/p>\n<p>Certes le concept m\u00eame peut para\u00eetre obscur au premier abord, mais Apple avec Swift a facilit\u00e9 les choses de par la syntaxe tr\u00e8s claire des protocoles.<\/p>\n<p>Et j'esp\u00e8re \u00e9galement que ce tutoriel vous aura ouvert les portes de la perception dans le cas o\u00f9 vous aviez encore des doutes \u00e0 propos de ces <code>delegate<\/code> que l'on voit souvent dans du code source d\u00e9di\u00e9 aux plateformes d'Apple. \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Qu&rsquo;est-ce qu&rsquo;un &quot;delegate&quot; ? On retrouve le principe de la d\u00e9l\u00e9gation partout dans OS X et iOS. Un champ de texte, par exemple, pr\u00e9vient son potentiel d\u00e9l\u00e9gu\u00e9 que l&rsquo;utilisateur est en train de taper du texte, a fini de taper, etc. Ceci dit, est-il utile d&rsquo;impl\u00e9menter nous-m\u00eame la d\u00e9l\u00e9gation dans nos objets ? Et comment&hellip; <a class=\"more-link\" href=\"https:\/\/www.aya.io\/blog\/qu-est-ce-qu-un-delegate\/\">Poursuivre la lecture <span class=\"screen-reader-text\">Qu&rsquo;est-ce qu&rsquo;un \u00ab\u00a0delegate\u00a0\u00bb ?<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":118,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,6,10],"tags":[],"class_list":["post-117","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-swift","category-tuto","entry"],"_links":{"self":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/117","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/comments?post=117"}],"version-history":[{"count":2,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/117\/revisions"}],"predecessor-version":[{"id":166,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/117\/revisions\/166"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/media\/118"}],"wp:attachment":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/media?parent=117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/categories?post=117"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/tags?post=117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}