{"id":3249,"date":"2017-10-25T10:10:36","date_gmt":"2017-10-25T14:10:36","guid":{"rendered":"\/cours\/xcode\/wp\/?page_id=3249"},"modified":"2017-10-25T10:10:36","modified_gmt":"2017-10-25T14:10:36","slug":"protocole_codable","status":"publish","type":"page","link":"https:\/\/ve2cuy.com\/xcode\/protocole_codable\/","title":{"rendered":"Utilisation d&#039;une &#039;API&#039; web.json.Codable"},"content":{"rendered":"<h1><\/h1>\n<hr \/>\n<h1>\u00a0Les \u00e9l\u00e9ments de\u00a0comp\u00e9tences de ce laboratoire<\/h1>\n<ul>\n<li><span style=\"color: #666699;\">Savoir utiliser ad\u00e9quatement le protocole &lsquo;Codable&rsquo; -&gt;\u00a0typealias Codable = Decodable &amp; Encodable.<\/span><\/li>\n<li><span style=\"color: #ff6600;\">Comprendre le r\u00f4le\u00a0des extensions de classes.<\/span><\/li>\n<li><span style=\"color: #008080;\">Savoir\u00a0programmer, en php, \u00a0une API Web proposant des donn\u00e9es selon l&rsquo;approche\u00a0<a style=\"color: #008080;\" title=\"RESTful\" href=\"http:\/\/fr.wikipedia.org\/w\/index.php?title=Representational_State_Transfer&amp;redirect=no\">RESTful<\/a>.<\/span><\/li>\n<li><span style=\"color: #993300;\">Comprendre l&rsquo;utilisation d&rsquo;une API RESTful dans une application Xcode; labo, La pens\u00e9e du jour.<\/span><\/li>\n<li><span style=\"color: #339966;\">Savoir\u00a0analyser une structure de donn\u00e9es json.<\/span><\/li>\n<li><span style=\"color: #ff0000;\">Savoir transposer des donn\u00e9es JSON en structures swift.<\/span><\/li>\n<li><span style=\"color: #333333;\">Pouvoir\u00a0programmer une application simple d&rsquo;affichage de la valeur, en temps r\u00e9el, d&rsquo;un portefeuille d&rsquo;actions.<\/span><\/li>\n<li><span style=\"color: #808000;\">Comprendre les traitements non bloquants d&rsquo;une application, <strong>G<\/strong>rand <strong>C<\/strong>entral <strong>D<\/strong>ispatch<\/span><\/li>\n<\/ul>\n<p><a href=\"\/xcode\/wp-content\/uploads\/2016\/10\/Chameleon-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft wp-image-2947 size-full\" src=\"\/xcode\/wp-content\/uploads\/2016\/10\/Chameleon-1.png\" alt=\"Chameleon-1\" width=\"200\" height=\"147\" \/><\/a><br \/>\n<strong>Pr\u00e9-requis:<\/strong><br \/>\nAvoir compl\u00e9t\u00e9 le tutoriel\u00a0<a href=\"\/xcode\/index.php\/labo\/timflix-delegation-et-uitableview-personnalisee\/\">TIMFlix<\/a>\u00a0ou bien le laboratoire &lsquo;<a href=\"\/xcode\/index.php\/les-amis-de-la-science\/\">Les amis de la science<\/a>&lsquo;, ou bien avoir une maitrise de l&rsquo;objet UITableView + segue + passage de param\u00e8tres entre les sc\u00e8nes d&rsquo;une app.<br \/>\n&nbsp;<\/p>\n<hr \/>\n<h1><b>Praeambulum<\/b><\/h1>\n<p>Dans le tutoriel\u00a0<a href=\"\/xcode\/index.php\/labo\/timflix-delegation-et-uitableview-personnalisee\/\">TIMFlix<\/a>\u00a0ou celui &lsquo;<a href=\"\/xcode\/index.php\/les-amis-de-la-science\/\">Des Amis de la science<\/a>&lsquo;, nous avons construit une application qui affichait une liste de donn\u00e9es\u00a0\u00e0 l&rsquo;int\u00e9rieur d&rsquo;un UITableView.<\/p>\n<ul>\n<li>Les donn\u00e9es\u00a0\u00e9taient renseign\u00e9es localement grace \u00e0 un fichier de propri\u00e9t\u00e9s.<\/li>\n<\/ul>\n<p><strong>L&rsquo;inconv\u00e9nient<\/strong> de cette approche est \u00e9vident lorsque vient le temps d&rsquo;y <strong>ajouter<\/strong> de nouvelles donn\u00e9es.<br \/>\n<strong>Dans ce tutoriel<\/strong>, nous verrons comment utiliser une API Web\u00a0comme source de\u00a0donn\u00e9es \u00e0 une application Xcode.<br \/>\nHistoriquement, il a toujours \u00e9t\u00e9 un peu complexe et lourd de traiter des donn\u00e9es en format JSON sous swift. \u00a0Nous pouvions nous rabattre sur des classes comme swiftyJSON pour all\u00e9ger la t\u00e2che.<br \/>\n\u00c0 partir de la version 4, \u00a0swift\u00a0propose les protocoles &lsquo;<strong>Decodable<\/strong>&lsquo; et &lsquo;<strong>Encodable<\/strong>&lsquo; pour le traitement facile des conversions de JSON vers des structures de donn\u00e9es natives au langage et vice versa. \u00a0L&rsquo;alias &lsquo;<strong>Codable&rsquo;<\/strong> repr\u00e9sente ses deux protocoles<br \/>\n<span style=\"color: #ff0000;\"><strong>Note<\/strong><\/span>: Le protocole &lsquo;<strong>Codable<\/strong>&lsquo; n&rsquo;est disponible qu&rsquo;\u00e0 partir de la version 4 de Xcode. \u00a0Ce laboratoire est aussi disponible, sans le protocole &lsquo;Codable&rsquo;, pour la\u00a0<a href=\"\/xcode\/index.php\/tim-ze-games\/\">version 3\u00a0de swift<\/a>.<\/p>\n<p style=\"text-align: right;\"><span style=\"color: #ff0000;\"><em>R\u00e9vision du 2017.10.25 &#8211; conversion vers Xcode 9.0, swift 4 et utilisation du protocole &lsquo;Codable&rsquo;.\u00a0<\/em><\/span><\/p>\n<hr \/>\n<p><iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"https:\/\/www.youtube.com\/embed\/Tv94swj4sjo?feature=oembed\" frameborder=\"0\" gesture=\"media\" allowfullscreen><\/iframe><\/p>\n<h1>1 &#8211; Une API web d&rsquo;acc\u00e8s \u00e0\u00a0des donn\u00e9es<\/h1>\n<h2>Explications<\/h2>\n<p>C&rsquo;est une \u00a0pratique courante que d&rsquo;offrir l&rsquo;acc\u00e8s \u00e0 des donn\u00e9es d&rsquo;un <span style=\"color: #003366;\"><strong>SGBD\u00a0<\/strong><\/span>(syst\u00e8me de gestion de la base de donn\u00e9es)<span style=\"color: #003366;\"><strong>\u00a0<\/strong><\/span> via des <strong>URLs<\/strong> web selon la m\u00e9thode\u00a0<a style=\"color: #0b0080;\" title=\"RESTful\" href=\"http:\/\/fr.wikipedia.org\/w\/index.php?title=Representational_State_Transfer&amp;redirect=no\">RESTful<\/a>.<br \/>\nL&rsquo;avantage de cette approche est qu&rsquo;il n&rsquo;est pas n\u00e9cessaire d&rsquo;offrir un acc\u00e8s direct au\u00a0SGBD de l&rsquo;organisation.<br \/>\n<span style=\"color: #003366;\"><strong>Exemples d&rsquo;acc\u00e8s direct au SGBD;<\/strong><\/span><\/p>\n<ul>\n<li>via une connexion \u00e0 la BD par programmation,<\/li>\n<li>par utilisation d&rsquo;outils comme phpMyAdmin, Oracle connect, &#8230;<\/li>\n<li>des\u00a0connaissances techniques du SGBD.<\/li>\n<\/ul>\n<p>Une\u00a0solution \u00e0 cet acc\u00e8s direct est d&rsquo;offrir des\u00a0<span style=\"color: #003366;\"><strong><span style=\"text-decoration: underline;\">scripts de type &lsquo;serveur web&rsquo; de traitements<\/span><\/strong><\/span>\u00a0et\u00a0<span style=\"color: #003366;\"><strong><span style=\"text-decoration: underline;\">d&rsquo;acc\u00e8s \u00e0 la base de donn\u00e9es<\/span><\/strong><\/span>.<br \/>\nCes scripts, \u00e9crits en\u00a0<span style=\"color: #003366;\"><strong>PHP<\/strong><\/span>,\u00a0<span style=\"color: #003366;\"><strong>ASP<\/strong><\/span>,\u00a0<strong style=\"color: #003366;\">Python<\/strong>\u00a0ou en\u00a0<span style=\"color: #003366;\"><strong>node,js<\/strong><\/span>, \u00a0peuvent alors \u00eatre lanc\u00e9s \u00e0 partir d&rsquo;une simple requ\u00eate <span style=\"color: #003366;\"><strong>HTTP<\/strong><\/span>, soit dans un fureteur ou \u00e0 partir d&rsquo;une application, en utilisant des fonctions ou des objets tel que\u00a0<span style=\"color: #003366;\"><strong>curl()<\/strong><\/span>,\u00a0<span style=\"color: #003366;\"><strong>NSArray(URL:)<\/strong><\/span>\u00a0et autres.<br \/>\nVoir la d\u00e9finition de\u00a0<a href=\"http:\/\/fr.wikipedia.org\/w\/index.php?title=Representational_State_Transfer&amp;redirect=no\">Representational State Transfer<\/a>.<\/p>\n<hr \/>\n<h1>2 &#8211; Le format des donn\u00e9es<\/h1>\n<p>Suite au traitement\u00a0des donn\u00e9es, le script serveur pourra retourner les donn\u00e9es dans un format ind\u00e9pendant du\u00a0SGBD tel que;<\/p>\n<ul>\n<li><span style=\"color: #003366;\"><strong><span style=\"color: #800000;\">Texte<\/span><br \/>\n<\/strong><\/span><\/li>\n<li><span style=\"color: #003366;\"><strong><span style=\"color: #333300;\">XML<\/span><br \/>\n<\/strong><\/span><\/li>\n<li><strong><span style=\"color: #003366;\">HTML<\/span><\/strong><\/li>\n<li><span style=\"color: #003366;\"><strong><span style=\"color: #000080;\">JSON<\/span><br \/>\n<\/strong><\/span><\/li>\n<li><span style=\"color: #003366;\"><strong><span style=\"color: #666699;\">CSV<\/span><br \/>\n<\/strong><\/span><\/li>\n<li><span style=\"color: #008000;\"><strong>PList<\/strong><\/span><\/li>\n<li><span style=\"color: #cc99ff;\"><strong>etc&#8230;<\/strong><\/span><\/li>\n<\/ul>\n<p><span style=\"color: #ff0000;\"><strong>Par exemple<\/strong><\/span>, l&rsquo;URL suivante,<br \/>\n<span style=\"color: #003366;\"><strong>https:\/\/uneApi.org\/obtenir_liste_stages.php?region=mtl&amp;format=csv,<\/strong><\/span><br \/>\nretourne\u00a0la liste des lieux de stages de\u00a0la r\u00e9gion de Montr\u00e9al en format csv:<\/p>\n<blockquote><p>&lsquo;Ubisoft&rsquo;,2,&rsquo;Hiv18&prime;<br \/>\n&lsquo;Gameloft&rsquo;,0,&rsquo;Hiv18&prime;<br \/>\n&lsquo;TIM.cie&rsquo;,7,&rsquo;\u00c9t\u00e959&prime;<\/p><\/blockquote>\n<hr \/>\n<h1>3 &#8211; Comment programmer une API Web<\/h1>\n<p>Pour programmer une <span style=\"color: #003366;\"><strong>API Web<\/strong><\/span> d&rsquo;acc\u00e8s \u00e0 une base de donn\u00e9es il suffit d&rsquo;avoir acc\u00e8s \u00e0 un serveur Web (<span style=\"color: #003366;\"><strong>IIS, Apache, &#8230;<\/strong><\/span>), \u00e0 un langage script cot\u00e9 serveur (<span style=\"color: #003366;\"><strong>php, ASP, node.JS, &#8230;<\/strong><\/span>) et \u00e0 un\u00a0SGBD\u00a0(<span style=\"color: #003366;\"><strong>MySQL, MSSQL, Oracle, PostgreSQL, &#8230;<\/strong><\/span>\u00a0).<br \/>\nDans le cadre d&rsquo;apprentissages, une solution comme\u00a0<strong><a href=\"http:\/\/www.wampserver.com\">WAMP<\/a>\u00a0<\/strong>ou <strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/LAMP_(software_bundle)\">LAMP<\/a><\/strong>\u00a0est id\u00e9ale.<\/p>\n<h2>Exemple pratique<\/h2>\n<p><strong>Voici comment programmer\u00a0une API Web, d&rsquo;interrogation d&rsquo;une table SQL, retournant une liste de pens\u00e9es du jour:\u00a0<\/strong><br \/>\n<span style=\"color: #ff0000;\"><strong>API.TIM.01<\/strong><\/span>\u00a0&#8211; \u00c0 partir d&rsquo;une table, &lsquo;<strong>penseesdujours<\/strong>&lsquo;:<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2191\" src=\"\/xcode\/wp-content\/uploads\/2014\/09\/apitim_01.png\" alt=\"apitim_01\" width=\"913\" height=\"323\" \/><br \/>\n<span style=\"color: #ff0000;\"><strong>API.TIM.02<\/strong><\/span>\u00a0&#8211; Et du script PHP suivant<\/p>\n<pre class=\"lang:php decode:true\">\/\/ Requ\u00eate SQL pour obtenir les enregistrements de la table penseesdujours\n\/\/ Connexion \u00e0 la BD\nmysql_connect(\"localhost\", \"user\", \"password\")  or die(mysql_error());\nmysql_select_db(\"cours_xcode\") or die(mysql_error());\n\/\/ Ex\u00e9cuter un requ\u00eate SQL\n$res = mysql_query(\"SELECT `nom_ajout` ,  `created_at` ,  `adresse_ip` , `pensee_texte`,  `pensee_auteur`,  `pensee_lien_image` FROM penseesdujours\") or die(mysql_error());\n\/\/ Parcourir les \u00e9l\u00e9ments du tableau de r\u00e9sultats\nwhile($r = mysql_fetch_assoc($res)) {\n  $xx = array_map(\"utf8_encode\", $r);\n  foreach ($xx as $key =&gt; $value) {\n    echo \"clef = $key, valeur = $value\\n\";\n  } \/\/ foreach\n} \/\/ while encore un r\u00e9sultat\n<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>API.TIM.03<\/strong><\/span>\u00a0&#8211; L&rsquo;API retournera le r\u00e9sultat texte suivant:<\/p>\n<blockquote><p>clef = nom_ajout, valeur = Alain<br \/>\nclef = created_at, valeur = 2014-11-01 05:11:43<br \/>\nclef = categorie, valeur = 3<br \/>\nclef = adresse_ip, valeur = 24.200.185.163<br \/>\nclef = pensee_texte, valeur = Il etait une fois un gars &#8230;<br \/>\nclef = pensee_auteur, valeur = Moi<br \/>\nclef = pensee_lien_image, valeur = http:\/\/www.imagesdoc.com\/var\/bayard\/storage\/images\/smk\/images-doc\/images\/images-doc-plus\/que-vois-tu\/photo-mystere-2-image-3\/24513202-1-fre-FR\/Photo-mystere-2-Image-3.jpg<\/p><\/blockquote>\n<p><a href=\"http:\/\/prof-tim.cstj.qc.ca\/cours\/xcode\/sources\/apitim.php\">\u00a0lien de test<\/a><br \/>\n<span style=\"color: #ff0000;\"><strong>API.TIM.04<\/strong><\/span>\u00a0&#8211; Voici un script PHP qui retourne le r\u00e9sultat en format &lsquo;<strong>Apple plist<\/strong>&lsquo;:<\/p>\n<pre class=\"lang:swift decode:true\">echo '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;'.\"\\n\";\necho '&lt;!DOCTYPE plist PUBLIC \"-\/\/Apple\/\/DTD PLIST 1.0\/\/EN\" \"http:\/\/www.apple.com\/DTDs\/PropertyList-1.0.dtd\"&gt;'.\"\\n\";\necho '&lt;plist version=\"1.0\"&gt;'.\"\\n\";\necho \"&lt;!-- Liste g\u00e9n\u00e9r\u00e9e par l'API TIM le \".date('Y-m-d h:m:s').\" --&gt;\\n\";\necho \"&lt;!-- (c) 2014-2016 par Alain Boudreault --&gt;\\n\";\necho \"&lt;array&gt;\\n\";\nwhile($r = mysql_fetch_assoc($res)) {\n  $xx = array_map(\"utf8_encode\", $r);\n  echo \"\\t&lt;dict&gt;\\n\";\n  foreach ($xx as $key =&gt; $value) {\n    echo \"\\t\\t&lt;key&gt;\".$key.\"&lt;\/key&gt;\\n\\t\\t&lt;string&gt;\".$value.\"&lt;\/string&gt;\\n\";\n  } \/\/ foreach\n  echo \"\\t&lt;\/dict&gt;\\n\";\n} \/\/ while\necho \"&lt;\/array&gt;\\n&lt;\/plist&gt;\";<\/pre>\n<p><span style=\"color: #008080;\"><strong>Note<\/strong><\/span>: Plusieurs classes du framework &lsquo;<strong>Foundation<\/strong>&lsquo; de <strong>Xcode<\/strong> savent travailler directement avec ce type de fichier. Voir la structure d&rsquo;un fichier &lsquo;plist&rsquo; sous Xcode:<br \/>\n<span style=\"color: #ff0000;\"><strong>API.TIM.05<\/strong><\/span>\u00a0&#8211;\u00a0Produira le\u00a0r\u00e9sultat suivant:<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;!DOCTYPE plist PUBLIC \"-\/\/Apple\/\/DTD PLIST 1.0\/\/EN\" \"http:\/\/www.apple.com\/DTDs\/PropertyList-1.0.dtd\"&gt;\n&lt;plist version=\"1.0\"&gt;\n&lt;!-- Liste g\u00e9n\u00e9r\u00e9e par l'API TIM le 2017-10-25 09:11:55 --&gt;\n&lt;!-- (c) 2014-2017 par Alain Boudreault --&gt;\n&lt;array&gt;\n\t&lt;dict&gt;\n\t\t&lt;key&gt;nom_ajout&lt;\/key&gt;\n\t\t&lt;string&gt;Alain&lt;\/string&gt;\n\t\t&lt;key&gt;created_at&lt;\/key&gt;\n\t\t&lt;string&gt;2014-11-01 06:11:47&lt;\/string&gt;\n\t\t&lt;key&gt;adresse_ip&lt;\/key&gt;\n\t\t&lt;string&gt;24.200.185.163&lt;\/string&gt;\n\t\t&lt;key&gt;pensee_texte&lt;\/key&gt;\n\t\t&lt;string&gt;On ne re\u00e7oit pas la sagesse, il faut la d\u00e9couvrir soi-m\u00eame, apr\u00e8s un trajet que personne ne peut faire pour nous, ne peut nous \u00e9pargner.&lt;\/string&gt;\n\t\t&lt;key&gt;pensee_auteur&lt;\/key&gt;\n\t\t&lt;string&gt;Marcel Proust&lt;\/string&gt;\n\t\t&lt;key&gt;pensee_lien_image&lt;\/key&gt;\n\t\t&lt;string&gt;http:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/7\/7e\/Marcel_Proust_1900.jpg\/220px-Marcel_Proust_1900.jpg&lt;\/string&gt;\n\t&lt;\/dict&gt;\n&lt;\/array&gt;\n&lt;\/plist&gt;\n<\/pre>\n<p><a href=\"http:\/\/prof-tim.cstj.qc.ca\/cours\/xcode\/sources\/apitim.php?mode=rnd&amp;quant=2&amp;format=plist\">lien de test\u00a0<\/a><br \/>\n<span style=\"color: #ff0000;\"><strong>API.TIM.06<\/strong><\/span>\u00a0&#8211; Un script PHP de mise en format\u00a0&lsquo;<a href=\"http:\/\/fr.wikipedia.org\/wiki\/JavaScript_Object_Notation\">JSON<\/a>&lsquo;<\/p>\n<pre class=\"lang:swift decode:true\">\/\/ tableau du r\u00e9sultat final\n$resultat = array();\n$resultat['info'] = array(\"API_TIM\" =&gt; \"version 2017.10.26\", \"type_requete\" =&gt; Input::get('mode'));\nwhile($r = mysql_fetch_assoc($res)) {\n  \/\/ Encoder les caract\u00e8res accentu\u00e9s.\n  $tableauAvecAccents[] = array_map(\"utf8_encode\", $r);\n} \/\/ while\n$resultat['resultat'] = $tableauAvecAccents;\n\/\/ Convertir un tableau en format JSON\necho json_encode($resultat);<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>API.TIM.07<\/strong><\/span>\u00a0&#8211;\u00a0Produira le\u00a0r\u00e9sultat suivant:<\/p>\n<pre class=\"lang:swift decode:true\">{\n  \"info\":{\"API_TIM\":\"version 2017.10.25\",\"type_requete\":\"rnd\"},\n  \"resultat\":[\n                { \"nom_ajout\":\"admin\",\n                  \"created_at\":\"2014-11-01 10:11:56\",\n                  \"adresse_ip\":\"24.200.185.163\",\n                  \"pensee_texte\":\"La qualit\\u00e9 d'un homme se calcule \\u00e0 sa d\\u00e9mesure ; tentez, essayez, \\u00e9chouez m\\u00eame, ce sera votre r\\u00e9ussite\\u0085\",\n                  \"pensee_auteur\":\"Jacques Brel\",\n                  \"pensee_lien_image\":\"https:\\\/\\\/encrypted-tbn2.gstatic.com\\\/images?q=tbn:ANd9GcQqWOL6fBMrhIECWoOuY3aEdxrm6biaZTdi5Kp72TC_xG9L11GS\"\n                },\n                ...\n             ]\n}<\/pre>\n<p><a href=\"http:\/\/prof-tim.cstj.qc.ca\/cours\/xcode\/sources\/apitim.php?mode=rnd&amp;quant=2&amp;format=json\">lien de test<\/a><br \/>\nExemple php complet:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\/\/ -------------------------------------------------------------------\n\/\/ Fichier:      apitim.php\n\/\/ Par:          Alain Boudreault\n\/\/ Date:         2016.10.23\n\/\/ -------------------------------------------------------------------\n\/\/ Description:  Exemple d'un script qui retourne, vers le client Web,\n\/\/               le contenu d'un table SQL dans un\n\/\/               des trois formats suivants:\n\/\/\n\/\/               texte, plist ou json.\n\/\/\n\/\/ Note:         Cette application a \u00e9t\u00e9 d\u00e9velopp\u00e9e pour les \u00e9tudiants\n\/\/               et \u00e9tudiantes du cours\n\/\/\n\/\/               ProductionMultim\u00e9diaSurSupport.tim.cstj.qc.ca\n\/\/ -------------------------------------------------------------------\n\/\/ M-A-J: A.B. 2017.10.25 - Ajout de commentaires\n\/\/        A.B. 2017.10.25 - Correction des dates\n\/\/ -------------------------------------------------------------------\n$servername = \"localhost\";\n$username   = \"votreAcces\";\n$password   = \"votreMotDePasse\";\n$dbname     = \"votreBD\";\n$mode   = isset($_GET[\"mode\"]) ? $_GET[\"mode\"] : \"all\";\n$quant  = isset($_GET[\"quant\"]) ? $_GET[\"quant\"] : \"2\";\n$format = isset($_GET[\"format\"]) ? $_GET[\"format\"] : \"texte\";\n\/\/ Create connection\n$conn = new mysqli($servername, $username, $password, $dbname);\n\/\/ Check connection\nif ($conn-&gt;connect_error) {\n    die(\"Connection failed: \" . $conn-&gt;connect_error);\n}\n$sql = \"SELECT `nom_ajout` ,  `created_at`, `categorie`, `adresse_ip` , `pensee_texte`,  `pensee_auteur`,  `pensee_lien_image`  FROM penseesdujours\";\nif ($mode == \"all\") {\n    $sql = \"SELECT `nom_ajout` ,  `created_at`, `categorie`, `adresse_ip` , `pensee_texte`,  `pensee_auteur`,  `pensee_lien_image` FROM penseesdujours\";\n}  \/\/ mode=all\nif ($mode == \"rnd\") {\n    $sql = \"SELECT `nom_ajout` ,  `created_at`,`categorie`, `adresse_ip` , `pensee_texte`,  `pensee_auteur`,  `pensee_lien_image` FROM penseesdujours ORDER BY RAND() LIMIT $quant\";\n} \/\/ mode=rnd\nif ($mode == \"adulte\") {\n    $sql = \"SELECT * FROM (SELECT `categorie`,`nom_ajout`, `created_at`, `adresse_ip`, `pensee_texte`, \" .\n\t\" `pensee_auteur`, `pensee_lien_image` FROM penseesdujours where categorie = 3) as tmp ORDER BY RAND() LIMIT $quant\";\n    echo $sql . \"\\n\\n\";\n} \/\/ mode=adulte\n$res = $conn-&gt;query($sql);\n\/\/ En format plist\nif ($format == \"plist\") {\n  echo '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;'.\"\\n\";\n  echo '&lt;!DOCTYPE plist PUBLIC \"-\/\/Apple\/\/DTD PLIST 1.0\/\/EN\" \"http:\/\/www.apple.com\/DTDs\/PropertyList-1.0.dtd\"&gt;'.\"\\n\";\n  echo '&lt;plist version=\"1.0\"&gt;'.\"\\n\";\n  echo \"&lt;!-- Liste g\u00e9n\u00e9r\u00e9e par l'API TIM le \".date('Y-m-d h:m:s').\" --&gt;\\n\";\n  echo \"&lt;!-- (c) 2014-2017 par Alain Boudreault --&gt;\\n\";\n  echo \"&lt;array&gt;\\n\";\n  while($r = $res-&gt;fetch_assoc()) {\n    $xx = array_map(\"utf8_encode\", $r);\n    echo \"\\t&lt;dict&gt;\\n\";\n    foreach ($xx as $key =&gt; $value) {\n      echo \"\\t\\t&lt;key&gt;\".$key.\"&lt;\/key&gt;\\n\\t\\t&lt;string&gt;\".$value.\"&lt;\/string&gt;\\n\";\n    } \/\/ foreach\n    echo \"\\t&lt;\/dict&gt;\\n\";\n  } \/\/ while\n  echo \"&lt;\/array&gt;\\n&lt;\/plist&gt;\";\n} \/\/ format = plist\n\/\/ En format texte\nif ($format == \"texte\") {\n  \/\/ Liste simple\n  while($row = $res-&gt;fetch_assoc()) {\n    foreach ($row as $key =&gt; $value) {\n       echo \"clef = \".$key.\", valeur = \".$value.\"&lt;br&gt;\\n\";\n     } \/\/ foreach\n  } \/\/ while\n} \/\/ if format == texte\n\/\/ En format json\nif ($format == \"json\") {\n  \/\/ tableau du r\u00e9sultat final\n  $resultat = array();\n  $resultat['info'] = array(\"API_TIM\" =&gt; \"version 2017.10.25\", \"type_requete\" =&gt; \"json\");\n  while($r = $res-&gt;fetch_assoc()) {\n    \/\/ Encoder les caract\u00e8res accentu\u00e9s.\n    $tableauAvecAccents[] = array_map(\"utf8_encode\", $r);\n  } \/\/ while\n  $resultat['resultat'] = $tableauAvecAccents;\n  \/\/ Convertir un tableau en format JSON\n  echo json_encode($resultat, JSON_PRETTY_PRINT);\n} \/\/ if format == json\n$conn-&gt;close();\n\/\/   echo phpinfo();\n?&gt;<\/pre>\n<hr \/>\n<h1>4\u00a0&#8211; Obtenir des donn\u00e9es json via une URL<\/h1>\n<p><span style=\"color: #008000;\">Nous allons maintenant analyser un projet qui utilise l&rsquo;API.TIM des pens\u00e9es du jour.<\/span><br \/>\n<strong>Le but\u00a0du projet est;<\/strong><\/p>\n<ul>\n<li><strong>d&rsquo;obtenir<\/strong> des donn\u00e9es, en format <strong>json<\/strong>, \u00a0via une URL Web,<\/li>\n<li><strong>de convertir<\/strong>\u00a0ces donn\u00e9es en utilisant des classes qui adoptent le protocole &lsquo;<strong>Codable<\/strong>&lsquo;<\/li>\n<li><strong>d&rsquo;afficher<\/strong> les donn\u00e9es \u00e0\u00a0l&rsquo;\u00e9cran.<\/li>\n<\/ul>\n<p><span style=\"color: #ff0000;\"><strong>Action<\/strong>\u00a0<strong>4.1<\/strong><\/span>\u00a0&#8211; <strong>Cloner le projet suivant :<\/strong><\/p>\n<pre class=\"lang:swift decode:true \">$ git clone https:\/\/github.com\/ve2cuy\/conversion-de-donnees-json-par-le-protocole-codable.git<\/pre>\n<p><em>\u00a0<\/em><br \/>\n<strong><span style=\"color: #ff0000;\">Action 4.2<\/span><\/strong>\u00a0&#8211; <strong>Analyser<\/strong>, en suivant les directives de l&rsquo;enseignant, \u00a0les fichiers de la <strong>branche &lsquo;master&rsquo;<\/strong><\/p>\n<pre class=\"lang:swift decode:true \">extension ViewController {\n    \/\/MARK:- Obtenir les donn\u00e9es\n    \/\/ =======================================================\n    func obtenirLaCitationDuJour(){\n       let uneURL = \"http:\/\/prof-tim.cstj.qc.ca\/cours\/xcode\/sources\/apitim.php?mode=rnd&amp;quant=5&amp;format=json\"\n        if let _data = NSData(contentsOf: URL(string: uneURL)!) as Data? {\n            \/\/ Note: Class.self veut dire \"de type Class\"\n            let donn\u00e9es = try! JSONDecoder().decode(Citation.self, from: _data)\n            print(donn\u00e9es)\n            for contenu in donn\u00e9es.resultat {\n                \/\/ Note: ?? est le 'nil-coalescing operator'\n                let auteur = contenu.pensee_auteur ?? \"Erreur: Nom de l'auteur non disponible\"\n                let pens\u00e9e = contenu.pensee_texte  ?? \"Erreur: Pens\u00e9e de l'auteur non disponible\"\n                print (\"\\(auteur) a dit:\\n\\t \\(pens\u00e9e)\\n\\n\")\n            }\n        } \/\/ if let\n    } \/\/ obtenirLaCitationDuJour()\n}<\/pre>\n<pre class=\"lang:swift decode:true \">\/\/  Citation.swift\n\/\/  --------------------------------------------\n\/\/  Created by Alain on 17-10-25.\n\/\/  Copyright \u00a9 2017 Alain. All rights reserved.\n\/\/\nimport Foundation\nclass Citation: Codable {\n    var info: Dictionary&lt;String, String&gt;\n    var resultat: Array&lt;DetailCitation&gt;\n} \/\/ Citation\nstruct DetailCitation:Codable {\n    var categorie: String\n    var pensee_auteur: String?\n    var pensee_texte: String?\n} \/\/ DetailCitation<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Action 4.3<\/strong><\/span> &#8211; Tester l&rsquo;application<br \/>\n<strong><span style=\"color: #ff0000;\">Action 4.4<\/span><\/strong> &#8211; \u00c0 r\u00e9aliser par l&rsquo;\u00e9tudiant,<br \/>\n<span style=\"color: #ff0000;\"><strong>a)<\/strong> <\/span>Remplacer la d\u00e9claration suivante:<\/p>\n<pre class=\"lang:swift decode:true\">    var info: Dictionary&lt;String, String&gt;<\/pre>\n<p>par la\u00a0structure &lsquo;<strong>Information<\/strong>&lsquo;<br \/>\n<strong><span style=\"color: #ff0000;\">Note<\/span><\/strong>: Il faut cr\u00e9er cette structure en observant les informations retourn\u00e9es par l&rsquo;API.<br \/>\n<span style=\"color: #ff0000;\"><strong>b)<\/strong> <\/span>Ajouter, \u00e0 la structure &lsquo;DetailCitation&rsquo;, une propri\u00e9t\u00e9 &#8211; de type optionnel &#8211; pour le lien de l&rsquo;image .<\/p>\n<hr \/>\n<h1>5 &#8211; L&rsquo;utilisation de l&rsquo;API &lsquo;finance&rsquo; de Yahoo<\/h1>\n<p>Yahoo offre des nombreuses APIs permettant d&rsquo;exploiter des donn\u00e9es de plusieurs domaines.<br \/>\nComme par exemple, la m\u00e9t\u00e9o, le taux de change des devises, la valeur des actions, &#8230;<br \/>\nVoici un exemple d&rsquo;interrogation du service des finances de Yahoo:<br \/>\n<a href=\"http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20%2a%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22%29%0A%09%09&amp;env=http%3A%2F%2Fdatatables.org%2Falltables.env&amp;format=json\">Obtenir cotes de la bourse via l&rsquo;API finance de Yahoo<\/a><br \/>\n\u00ab\u00a0&amp;env=store:\/\/datatables.org\/alltableswithkeys&amp;format=json\u00a0\u00bb<br \/>\nRetourne\u00a0la structure suivante:<\/p>\n<pre class=\"lang:default decode:true \">{\n    \"query\":{  \/\/ Dictionary&lt;String, Any&gt;\n             \"count\":4,\n             \"created\":\"2016-11-01T15:53:16Z\",\n             \"lang\":\"fr-ca\",\n             \"results\": {  \/\/ Dictionary&lt;String, Any&gt;\n                  \/\/ *** Tableau des cotes\n\t\t  \"quote\":[ \/\/ Array&lt;Dictionary&lt;String, Any&gt;&gt;\n\t\t    \/\/ ****  Premier \u00e9l\u00e9ment\n\t          {     \"symbol\":\"YHOO\",\n   \t                \"Ask\":\"40.89\",\n     \t\t        \"AverageDailyVolume\":\"10498500\",\n        \t        \"Bid\":\"40.86\",\n          \t        \"AskRealtime\":null,\n                    \"BidRealtime\":null,\n                    \"BookValue\":\"36.39\",\n                    \"Change_PercentChange\":\"-0.23 - -0.55%\",\n                    \"Change\":\"-0.23\",\n                    \"Commission\":null,\n                    \"Currency\":\"USD\",\n                    \"ChangeRealtime\":null,\n                    \"AfterHoursChangeRealtime\":null,\n                    \"DividendShare\":null,\n                    \"LastTradeDate\":\"10\/31\/2016\",\n                    \"TradeDate\":null,\n                    \"EarningsShare\":\"-5.11\",\n                    \"ErrorIndicationreturnedforsymbolchangedinvalid\":null,\n                    \"EPSEstimateCurrentYear\":\"0.58\",\n                    \"EPSEstimateNextYear\":\"0.62\",\n                    \"EPSEstimateNextQuarter\":\"0.14\",\n                    \"DaysLow\":null,\n                    \"DaysHigh\":null,\n                    \"YearLow\":\"26.15\",\n                    \"YearHigh\":\"44.92\",\n                    \"HoldingsGainPercent\":null,\n                    \"AnnualizedGain\":null,\n                    \"HoldingsGain\":null,\n                    \"HoldingsGainPercentRealtime\":null,\n                    \"HoldingsGainRealtime\":null,\n                    \"MoreInfo\":null,\n                    \"OrderBookRealtime\":null,\n                    \"MarketCapitalization\":\"39.78B\",\n                    \"MarketCapRealtime\":null,\n                    \"EBITDA\":\"90.38M\",\n                    \"ChangeFromYearLow\":\"15.40\",\n                    \"PercentChangeFromYearLow\":\"+58.89%\",\n                    \"LastTradeRealtimeWithTime\":null,\n                    \"ChangePercentRealtime\":null,\n                    \"ChangeFromYearHigh\":\"-3.37\",\n                    \"PercebtChangeFromYearHigh\":\"-7.50%\",\n                    \"LastTradeWithTime\":\"4:00pm - &lt;b&gt;41.55&lt;\/b&gt;\",\n                    \"LastTradePriceOnly\":\"41.55\",\n                    \"HighLimit\":null,\n                    \"LowLimit\":null,\n                    \"DaysRange\":null,\n                    \"DaysRangeRealtime\":null,\n                    \"FiftydayMovingAverage\":\"42.83\",\n                    \"TwoHundreddayMovingAverage\":\"39.65\",\n                    \"ChangeFromTwoHundreddayMovingAverage\":\"1.90\",\n                    \"PercentChangeFromTwoHundreddayMovingAverage\":\"+4.78%\",\n                    \"ChangeFromFiftydayMovingAverage\":\"-1.28\",\n                    \"PercentChangeFromFiftydayMovingAverage\":\"-2.98%\",\n                    \"Name\":\"Yahoo! Inc.\",\n                    \"Notes\":null,\n                    \"Open\":null,\n                    \"PreviousClose\":\"41.78\",\n                    \"PricePaid\":null,\n                    \"ChangeinPercent\":\"-0.55%\",\n                    \"PriceSales\":\"8.04\",\n                    \"PriceBook\":\"1.15\",\n                    \"ExDividendDate\":null,\n                    \"PERatio\":null,\n                    \"DividendPayDate\":null,\n                    \"PERatioRealtime\":null,\n                    \"PEGRatio\":\"-124.19\",\n                    \"PriceEPSEstimateCurrentYear\":\"71.64\",\n                    \"PriceEPSEstimateNextYear\":\"67.02\",\n                    \"Symbol\":\"YHOO\",\n                    \"SharesOwned\":null,\n                    \"ShortRatio\":\"4.25\",\n                    \"LastTradeTime\":\"4:00pm\",\n                    \"TickerTrend\":null,\n                    \"OneyrTargetPrice\":\"45.14\",\n                    \"Volume\":\"10108\",\n                    \"HoldingsValue\":null,\n                    \"HoldingsValueRealtime\":null,\n                    \"YearRange\":\"26.15 - 44.92\",\n                    \"DaysValueChange\":null,\n                    \"DaysValueChangeRealtime\":null,\n                    \"StockExchange\":\"NMS\",\n                    \"DividendYield\":null,\n                    \"PercentChange\":\"-0.55%\"},\n                    \/\/ *** Deuxi\u00e8me \u00e9l\u00e9ment\n                    {\"symbol\":\"AAPL\",\"Ask\":\"113.60\", ... }\n\t\t] \/\/ **** Fin du tableau des cotes\n\t   }  \/\/ results\n     } \/\/ query\n}<\/pre>\n<hr \/>\n<p>&nbsp;<br \/>\nVoici comment obtenir et traiter ces donn\u00e9es:<\/p>\n<pre class=\"lang:swift decode:true\">    \/\/ =======================================================\n    func obtenirDonn\u00e9esDeMesActions(){\n        \/\/ Exemple d'utilisation de l'API finance Yahoo:\n        \/\/ http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select * from yahoo.finance.quotes where symbol in ('MSFT','YHOO','FB','INTC','HPQ','AAPL','AMD','COKE')&amp;env=store:\/\/datatables.org\/alltableswithkeys&amp;format=json\n        \/\/ Il faudra convertir certains caract\u00e8res en s\u00e9quence d'\u00e9chappement WEB\n        \/\/ pour rendre l'URL compatible avec la classe URL.\n        \/\/ http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20('MSFT','YHOO','FB','INTC','HPQ','AAPL','AMD','COKE')&amp;env=store:\/\/datatables.org\/alltableswithkeys&amp;format=json\n        \/\/ Construire l'URL vers l'API finance de Yahoo et remplacer les caract\u00e8res invalides.\n        \/\/ Liste des car \u00e0 convertir\n        let caracteresAConvertirEnFormatWeb = CharacterSet(charactersIn: \" \").inverted\n        \/\/ Former le d\u00e9but de l'URL\n        let uneURL = \"http:\/\/query.yahooapis.com\/v1\/public\/yql?q=\"\n            \/\/ Ajouter la requ\u00eate SQL et remplacer les ' ' par %20\n            + \"select * from yahoo.finance.quotes where symbol in ('MSFT','YHOO','FB','INTC','HPQ','AAPL','AMD','COKE')\".addingPercentEncoding(withAllowedCharacters: caracteresAConvertirEnFormatWeb)!\n            \/\/ Ajouter la fin de l'URL\n            + \"&amp;env=store:\/\/datatables.org\/alltableswithkeys&amp;format=json\"\n        \/\/MARK:- Ex\u00e9cuter la commande seulement en mode DEBUG\n        #if DEBUG\n         print(uneURL)\n        #endif\n        if let _data = NSData(contentsOf: URL(string: uneURL)!) as Data? {\n            \/\/ Note: YahooFinance veut dire \"de type YahooFinance\"\n            let donn\u00e9es = try! JSONDecoder().decode(YahooFinance.self, from: _data)\n            print(donn\u00e9es)\n            for contenu in donn\u00e9es.query.results.quote {\n                let prix = contenu.Ask ?? \"Prix non disponible\"\n                print (\"\\(contenu.Symbol): \\(prix)\")\n            }\n        } \/\/ if let\n    } \/\/ obtenirDonn\u00e9esDeMesActions<\/pre>\n<p>&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>Action 5.1<\/strong><\/span>\u00a0&#8211; Enlever le commentaire devant la ligne: &lsquo;\/\/ obtenirDonn\u00e9esDeMesActions()&rsquo; et Tester l&rsquo;application.<br \/>\n<strong>R\u00e9sultat obtenu:<\/strong><\/p>\n<pre class=\"lang:swift decode:true\">MSFT: 79.07\nYHOO: Prix non disponible\nFB: 171.10\nINTC: 40.90\nHPQ: 21.640\nAAPL: 157.53\nAMD: 12.0800\nCOKE: 225.5000<\/pre>\n<p>L&rsquo;affichage est r\u00e9alis\u00e9 par le code suivant:<\/p>\n<pre class=\"lang:swift decode:true\">\/\/ Afficher le symbole ainsi que le prix des actions.\nfor contenu in donn\u00e9es.query.results.quote {\n    let prix = contenu.Ask ?? \"Prix non disponible\"\n    print (\"\\(contenu.Symbol): \\(prix)\")\n}\n<\/pre>\n<hr \/>\n<h1>6 &#8211; Ex\u00e9cution d&rsquo;une requ\u00eate en parall\u00e8le avec l&rsquo;application:<\/h1>\n<p><span style=\"color: #ff0000;\"><strong>Action 6.1<\/strong><\/span>\u00a0&#8211; Faire\u00a0un &lsquo;<strong>checkout<\/strong>&lsquo; sur la branche &lsquo;CGDDepart&rsquo; du projet pr\u00e9c\u00e9dent.<br \/>\n<strong><span style=\"color: #ff0000;\">Action 6.2<\/span><\/strong> &#8211; Analyser le code suivant:<\/p>\n<pre class=\"lang:swift decode:true \">    override func viewDidLoad() {\n        super.viewDidLoad()\n        obtenirDonn\u00e9esDeMesActions()\n        afficherDonn\u00e9esFinanceYahoo()\n    } \/\/ viewDidLoad()<\/pre>\n<p>&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>Action 6.3<\/strong><\/span> &#8211; Tester l&rsquo;application.<\/p>\n<pre class=\"lang:swift decode:true \">============================================\nVoici les donn\u00e9es du portefeuille d'actions:\nD\u00e9but -------------------------------------&gt;\n\tMSFT: 84.00\n\tYHOO: Prix non disponible\n\tFB: 177.87\n\tINTC: 44.60\n\tHPQ: Prix non disponible\n\tAAPL: 162.94\n\tAMD: 11.84\n\tCOKE: Prix non disponible\nFin &lt;---------------------------------------<\/pre>\n<p>&nbsp;<br \/>\n<strong><span style=\"color: #ff0000;\">Action 6.4<\/span><\/strong> &#8211; Retirer le commentaire des lignes suivantes (2 et 8):<\/p>\n<pre class=\"lang:swift mark:2,8 decode:true\">        \/\/ TODO: Retirer le commentaire suivant\n        \/\/ DispatchQueue.main.async ( execute: {\n            \/\/ Obtenir les donn\u00e9es via le Web\n            if let _data = NSData(contentsOf: URL(string: uneURL)!) as Data? {\n                \/\/ Note: YahooFinance.self veut dire \"de type YahooFinance\"\n                self.donn\u00e9esFinanceYahoo = try! JSONDecoder().decode(YahooFinance.self, from: _data)\n            } \/\/ if let\n        \/\/ TODO: Retirer le commentaire suivant\n        \/\/ }) \/\/ DispatchQueue()<\/pre>\n<p>&nbsp;<br \/>\n<span style=\"color: #ff0000;\"><strong>Action 6.5<\/strong><\/span> &#8211; Tester l&rsquo;application.<br \/>\nAnalysons le r\u00e9sultat obtenu:<\/p>\n<pre class=\"lang:swift decode:true\">============================================\nVoici les donn\u00e9es du portefeuille d'actions:\nD\u00e9but -------------------------------------&gt;\nFin &lt;---------------------------------------<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Note:<\/strong><\/span> La liste est vide.<br \/>\n<span style=\"color: #008080;\"><strong>Raison<\/strong><\/span>:\u00a0Nous affichons le contenu du tableau avant d&rsquo;avoir re\u00e7u la r\u00e9ponse de l&rsquo;API.<br \/>\nPr\u00e9c\u00e9demment, l&rsquo;ex\u00e9cution du programme bloquait \u00e0 la lecture des donn\u00e9es \u00e0 partir d&rsquo;Internet.<br \/>\nMaintenant, avec &lsquo;\u00a0<span style=\"color: #008080;\"><strong>DispatchQueue.main.async ( execute:\u00a0&lsquo;,\u00a0<\/strong><\/span>la lecture des donn\u00e9es est faite en arri\u00e8re plan et notre programme principal continu les traitements.<\/p>\n<pre class=\"lang:swift decode:true\">obtenirDonn\u00e9esDeMesActions()   \/\/ Envoy\u00e9 en arri\u00e8re plan\nafficherDonn\u00e9esFinanceYahoo()  \/\/ *** N'attend plus apr\u00e8s l'instruction pr\u00e9c\u00e9dente.<\/pre>\n<p>Avec cette technique, <span style=\"color: #666699;\"><em>il faut traiter l&rsquo;affichage des donn\u00e9es et l&rsquo;actualisation des composants MVC \u00e0 l&rsquo;int\u00e9rieur du bloc de code du &lsquo;dispatch&rsquo;<\/em><\/span> (inline function, fonction anonyme).<br \/>\nDe plus, dans ce bloc, les variables doivent-\u00eatre pr\u00e9c\u00e9d\u00e9es du mot cl\u00e9 \u00a0&lsquo;<strong>self<\/strong>&lsquo;. \u00a0Par exemple,<\/p>\n<pre class=\"lang:swift decode:true\">self.donn\u00e9esFinanceYahoo = try! JSONDecoder().decode(YahooFinance.self, from: _data)\nself.unTableView.reloadData()\nself.nbLectures += 1\nself.afficherDonn\u00e9esFinanceYahoo()<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Action 6.6<\/strong><\/span> &#8211; Retirer le commentaire suivant<\/p>\n<pre class=\"lang:swift decode:true \">\/\/ Action 6.6 - Retirer le commentaire suivant\n\/\/ self.afficherDonn\u00e9esFinanceYahoo()<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Action 6.7<\/strong><\/span> &#8211; Tester l&rsquo;application<\/p>\n<hr \/>\n<h2>6.8 Lire\u00a0les donn\u00e9es dans une boucle de temps<\/h2>\n<p><span style=\"color: #ff0000;\"><strong>Action 6.9<\/strong><\/span>\u00a0&#8211; Retire le commentaire des lignes suivantes (3):<\/p>\n<pre class=\"lang:swift mark:3 decode:true\">    func viewDidLoad() {\n    ...\n    \/\/ Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(self.obtenirDonn\u00e9esDeMesActions), userInfo: nil, repeats: true)\n    }<\/pre>\n<pre class=\"lang:swift mark:4-5 decode:true\">\/\/ Dans DispatchQueue.main.async :\n\/\/ TODO: Action 6.9 - Enlever les commentaires \u00e0 l'\u00e9tape du 'timer'\n\/\/ self.nbLectures += 1\n\/\/ print(\"\\n\\n\\(NSDate()) - Lecture num\u00e9ro \\(self.nbLectures)\")\n<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Action 6.10<\/strong><\/span> &#8211; Tester l&rsquo;application:<\/p>\n<pre class=\"lang:swift mark:6,22 decode:true \">2017-10-28 15:56:33 +0000 - Lecture num\u00e9ro 1\n============================================\nVoici les donn\u00e9es du portefeuille d'actions:\nD\u00e9but -------------------------------------&gt;\n\tMSFT: 84.00\n\tYHOO: Prix non disponible\n\tFB: 177.87\n\tINTC: 44.60\n\tHPQ: Prix non disponible\n\tAAPL: 162.94\n\tAMD: 11.84\n\tCOKE: Prix non disponible\nFin &lt;---------------------------------------\n2017-10-28 15:56:43 +0000 - Lecture num\u00e9ro 2\n============================================\nVoici les donn\u00e9es du portefeuille d'actions:\nD\u00e9but -------------------------------------&gt;\n\tMSFT: 83.75\n\tYHOO: Prix non disponible\n\tFB: 178.50\n\tINTC: 38.67\n\tHPQ: Prix non disponible\n\tAAPL: 162.99\n\tAMD: 11.80\n\tCOKE: Prix non disponible\nFin &lt;---------------------------------------<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Note<\/strong><\/span>: la version finale est disponible via la branche &lsquo;<strong>GCDFinale&rsquo;<\/strong><\/p>\n<hr \/>\n<h1>7 &#8211; Application de consultation\u00a0du portefeuille d&rsquo;actions<\/h1>\n<p><strong><span style=\"color: #ff0000;\">Action 7.1<\/span><\/strong> &#8211; Passer \u00e0 la branche &lsquo;<strong>tableView<\/strong>&lsquo; du projet Xcode.<br \/>\n<strong><span style=\"color: #ff0000;\">Action 7.2<\/span><\/strong> &#8211; Tester l&rsquo;application<br \/>\n<span style=\"color: #ff0000;\"><strong>Action 7.3<\/strong><\/span> &#8211; Analyser le code du projet<\/p>\n<hr \/>\n<h1><span style=\"color: #ff0000;\">7.4 &#8211;\u00a0Laboratoire \u00e0 faire en classe<\/span><\/h1>\n<ol>\n<li style=\"text-align: left;\">Il faut remplacer les donn\u00e9es du portefeuille &lsquo;cod\u00e9es en dur&rsquo; par les donn\u00e9es du fichier &lsquo;portefeuille.json&rsquo;<\/li>\n<li style=\"text-align: left;\">Afficher dans la console, \u00a0la quantit\u00e9 d&rsquo;actions, le prix de l&rsquo;action, le total de la valeur (quant * prix) et la valeur du portefeuille.\u00a0<strong>Attention<\/strong>, la quantit\u00e9 est optionnelle dans le fichier de donn\u00e9es.<\/li>\n<\/ol>\n<pre class=\"lang:swift mark:8 decode:true\">\/\/ Le fichier json\n{\n    \"actions\" : [\n                 { \"symbole\" : \"MSFT\", \"quant\" : 5 },\n                 { \"symbole\" : \"FB\", \"quant\" : 10 },\n                 { \"symbole\" : \"AAPL\", \"quant\" : 25 },\n                 { \"symbole\" : \"AMD\", \"quant\" : 50 },\n                 { \"symbole\" : \"MOMO\" }\n    ]\n}<\/pre>\n<p>R\u00e9sultat de la console:<\/p>\n<pre class=\"lang:swift mark:8 decode:true\">============================================\nVoici les donn\u00e9es du portefeuille d'actions:\nD\u00e9but -------------------------------------&gt;\n\tMSFT: 5 \u00e0 84.00 = 420.0\n\tFB: 10 \u00e0 177.87 = 1778.7\n\tAAPL: 25 \u00e0 162.94 = 4073.5\n\tAMD: 50 \u00e0 11.84 = 592.0\n\tMOMO: 0 \u00e0 30.54 = 0.0\nLa valeur du portefeuille est de 6864.2 $\nFin &lt;---------------------------------------<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Note<\/strong><\/span>: On charge un fichier json local, de la fa\u00e7on suivante:<\/p>\n<pre class=\"lang:swift decode:true\">if let _data = NSData(contentsOfFile: pathFichierPlist) as Data? {\n  ...\n}<\/pre>\n<p><strong><span style=\"color: #ff0000;\">Indice<\/span><\/strong>: Les actions seront \u00e0 la m\u00eame position dans le tableau du portefeuille et la tableau des donn\u00e9es de Yahoo.<\/p>\n<hr \/>\n<h1><span style=\"color: #ff0000;\">7.5 &#8211;\u00a0Laboratoire \u00e0 faire en classe<\/span><\/h1>\n<h3><span style=\"color: #666699;\">Choix 1 &#8211; Valeurs de conversion des devises en fonction du dollar am\u00e9ricain.<\/span><\/h3>\n<p>Obtenir la valeur des monnaies en fonction de USD \u00e0 partir de l&rsquo;API suivante:<br \/>\n<span style=\"color: #ff0000;\"><a href=\"http:\/\/finance.yahoo.com\/webservice\/v1\/symbols\/allcurrencies\/quote?format=json\">http:\/\/finance.yahoo.com\/webservice\/v1\/symbols\/allcurrencies\/quote?format=json<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\"><strong>Action<\/strong><\/span>: \u00c9crire une application qui affiche, dans un UITableView, le Code (symbol) des devises ainsi que le prix (price). \u00a0Actualiser les donn\u00e9es \u00e0 chaque 15\u00a0secondes.<\/p>\n<h3><span style=\"color: #666699;\">Choix 2 (d\u00e9fi plus \u00e9lev\u00e9)\u00a0&#8211; La temp\u00e9rature en temp r\u00e9el de 10 villes\u00a0<\/span><\/h3>\n<p>Obtenir la temp\u00e9rature\u00a0\u00e0 partir de l&rsquo;API suivante:<br \/>\n<a href=\"https:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20*%0Afrom%20weather.forecast%0Awhere%20woeid%20in%20(3534%2C3518%2C3444%2C615702%2C2459115%2C742676%2C1118370%2C44418%2C212226%2C2151443)%0Aand%20u%20%3D%20'C'%3B&amp;format=json&amp;diagnostics=true&amp;callback=\">Temp\u00e9rature de 10 villes<\/a><br \/>\n<span style=\"color: #ff0000;\"><strong>Action<\/strong><\/span>: \u00c9crire une application qui affiche, dans un UITableView, le nom de la ville\u00a0ainsi que la temp\u00e9rature actuelle. \u00a0Actualiser les donn\u00e9es \u00e0 chaque 15\u00a0secondes.<br \/>\n<strong><span style=\"color: #ff0000;\">Astuce<\/span><\/strong>: Pour consulter les donn\u00e9es json en format structur\u00e9, copier le r\u00e9sultat json dans Brackets et afficher avec le plugin &lsquo;Pretty Json&rsquo;<\/p>\n<hr \/>\n<h1>Projet &#8211;\u00a0\u00a0TIM.Ze.Game<\/h1>\n<h3>Exemple d&rsquo;un projet utilisant une libraire externe pour obtenir les images web.<\/h3>\n<p>R\u00e9sultat final:<br \/>\n<iframe loading=\"lazy\" width=\"700\" height=\"394\" src=\"https:\/\/www.youtube.com\/embed\/XnILt8LieI4?feature=oembed\" frameborder=\"0\" gesture=\"media\" allowfullscreen><\/iframe><\/p>\n<hr \/>\n<h2>Mise en context:<\/h2>\n<p>Ce projet utilise un librairie externe pour la lecture des images \u00e0 partir d&rsquo;une URL;<br \/>\n<strong>SDWebImage<\/strong> disponible <a href=\"https:\/\/github.com\/rs\/SDWebImage\">ici<\/a>.<br \/>\nLa librairie n&rsquo;est pas incluse avec le projet, par contre, elle y est r\u00e9f\u00e9r\u00e9e.<br \/>\nIl sera de la responsabilit\u00e9 de l&rsquo;utilisateur d&rsquo;ajouter les \u00e9l\u00e9ments manquants, requis pour le bon fonctionnement du projet.<br \/>\nUne fa\u00e7on simple est d&rsquo;utiliser\u00a0<a href=\"https:\/\/cocoapods.org\">cocoapods<\/a><br \/>\nVoici:\u00a0<a href=\"https:\/\/github.com\/vsouza\/awesome-ios\">Une liste de librairies pour Xcode<\/a><br \/>\nVoici une autre liste :<br \/>\n<a href=\"https:\/\/medium.com\/app-coder-io\/33-ios-open-source-libraries-that-will-dominate-2017-4762cf3ce449\">https:\/\/medium.com\/app-coder-io\/33-ios-open-source-libraries-that-will-dominate-2017-4762cf3ce449<\/a><br \/>\nVoici un carrousel :\u00a0<a href=\"https:\/\/github.com\/nicklockwood\/iCarousel\">https:\/\/github.com\/nicklockwood\/iCarousel<\/a><br \/>\nUn player video:\u00a0<a href=\"https:\/\/github.com\/mobileplayer\/mobileplayer-ios\">https:\/\/github.com\/mobileplayer\/mobileplayer-ios<\/a><\/p>\n<hr \/>\n<h3>Installation d&rsquo;un librairie via cocoapods<\/h3>\n<p>Comment?<br \/>\n<span style=\"color: #ff0000;\"><strong>1 &#8211;<\/strong><\/span>\u00a0v\u00e9rifier si cocoapods est install\u00e9e sur votre poste en tapant &lsquo;<strong>pod &#8211;version<\/strong>&lsquo; \u00a0dans la fen\u00eatre terminal.<br \/>\n<strong><span style=\"color: #ff0000;\">2 &#8211;<\/span> <\/strong>Au besoin, il faudra l&rsquo;installer:<\/p>\n<pre class=\"highlight\">$ sudo gem install cocoapods<\/pre>\n<p>ou par &lsquo;<a href=\"https:\/\/brew.sh\/index_fr.html\">homebrew<\/a>&lsquo;<\/p>\n<pre><code>$ brew install cocoapods<\/code><\/pre>\n<p><span style=\"color: #ff0000;\"><strong>3 &#8211;<\/strong> <\/span>Dans le dossier de l&rsquo;application, cr\u00e9er un fichier nomm\u00e9 &lsquo;<strong>Podfile<\/strong>&lsquo; renseignant les libraires \u00e0 installer.<br \/>\npar exemple, pour le projet courant: <a href=\"\/xcode\/wp-content\/uploads\/2017\/10\/Podfile.zip\">Podfile<\/a><\/p>\n<pre class=\"lang:swift decode:true\">platform :ios, '8.0'\nuse_frameworks!\ntarget 'MonDuProjet' do\n\tpod 'SDWebImage', '~&gt; 4.0'\nend\n<\/pre>\n<p>Voici un autre exemple<\/p>\n<pre class=\"lang:swift decode:true \">platform :ios, '8.0'\nuse_frameworks!\ntarget 'MyApp' do\n  pod 'AFNetworking', '~&gt; 2.6'\n  pod 'ORStackView', '~&gt; 3.0'\n  pod 'SwiftyJSON', '~&gt; 2.3'\nend<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>4 &#8211;<\/strong> <\/span>Taper la commande suivante:<\/p>\n<pre class=\"lang:swift decode:true \">$ pod install<\/pre>\n<p><strong>Note<\/strong>: La librairie devrait \u00eatre install\u00e9e et un espace de travail Xcode &lsquo;xcworkspace&rsquo; cr\u00e9\u00e9.<br \/>\n<span style=\"color: #ff0000;\"><strong>5 &#8211;<\/strong> <\/span>Ouvrir le projet en utilisant le fichier &lsquo;<strong>nomDeApp<\/strong>.xcworkspace&rsquo;<\/p>\n<pre class=\"highlight\">$ open App.xcworkspace<\/pre>\n<p><span style=\"color: #ff0000;\"><strong>Exercice<\/strong><\/span><br \/>\n1 &#8211; Cr\u00e9er un nouveau projet Xcode &lsquo;testPod&rsquo;.<br \/>\n2 &#8211; Fermer le projet<br \/>\n3 &#8211; Cr\u00e9er un nouveau fichier nomm\u00e9 &lsquo;Podfile&rsquo; avec le contenu suivant &#8211; et enregistrer dans le dossier de l&rsquo;application<\/p>\n<pre class=\"lang:swift decode:true\">platform :ios, '8.0'\nuse_frameworks!\ntarget 'testPod' do\n\tpod 'SDWebImage', '~&gt; 4.0'\nend<\/pre>\n<p>4 &#8211; Ouvrir une fen\u00eatre &lsquo;terminal&rsquo; dans le dossier de l&rsquo;application<br \/>\n5 &#8211; Ex\u00e9cuter la commande &lsquo;$ pod install&rsquo;<br \/>\n6 &#8211; Ouvrir le &lsquo;workspace&rsquo;<\/p>\n<hr \/>\n<p><span style=\"color: #ff0000;\"><strong>Action<\/strong><\/span> &#8211; Cloner le projet \u00e0 l&rsquo;adresse suivante: \u00a0<span style=\"color: #666699;\">https:\/\/github.com\/ve2cuy\/tim.ze.games.2017<\/span><\/p>\n<pre class=\"lang:swift decode:true \">$ git clone https:\/\/github.com\/ve2cuy\/tim.ze.games.2017 --branch versionFinale<\/pre>\n<p>&nbsp;<br \/>\nLien du projet sur GitHub:\u00a0<a href=\"https:\/\/github.com\/ve2cuy\/tim.ze.games.2017\">tim.ze.games<\/a><br \/>\nVersion locale compl\u00e8te:\u00a0<a href=\"\/xcode\/wp-content\/uploads\/2017\/10\/tim.ze_.games_.v2017.01.zip\">tim.ze.games.v2017.01<\/a><br \/>\n<span style=\"color: #ff0000;\"><strong>Action<\/strong><\/span> &#8211; Analyse du projet &#8211; Suivre les directives en classe<br \/>\nNote: Ce projet pr\u00e9sente, entre autre, des animations de propri\u00e9t\u00e9s ainsi que la lecture d&rsquo;une trame sonore.<br \/>\n&nbsp;<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<h1>Autres APIs<\/h1>\n<p>Voici une liste d&rsquo;APIs disponibles via le web:<\/p>\n<h2>R\u00e9pertoire d&rsquo;APIs web<\/h2>\n<p><a href=\"http:\/\/www.programmableweb.com\/apis\/directory\">http:\/\/www.programmableweb.com\/apis\/directory<\/a><\/p>\n<h2>M\u00e9t\u00e9o sur Yahoo<\/h2>\n<p><a href=\"http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%22CAXX0301%22&amp;format=json\">http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%22<span style=\"color: #ff0000;\">CAXX0301<\/span>%22&amp;format=json<\/a><br \/>\nCe qui donne la m\u00e9t\u00e9o pour Montr\u00e9al (CAXX0301)<br \/>\nVoir: \u00a0<a href=\"http:\/\/developer.yahoo.com\/yql\/\">http:\/\/developer.yahoo.com\/yql\/<\/a><\/p>\n<h2>Trouvez le UID d&rsquo;une ville<\/h2>\n<p><a href=\"http:\/\/wxdata.weather.com\/wxdata\/search\/search?where=montr\">http:\/\/wxdata.weather.com\/wxdata\/search\/search?where=montr<\/a><\/p>\n<h2>Cotes de la bourse sur Yahoo<\/h2>\n<p><a href=\"http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20%2a%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22%29%0A%09%09&amp;env=http%3A%2F%2Fdatatables.org%2Falltables.env&amp;format=json\">http:\/\/query.yahooapis.com\/v1\/public\/yql?q=select%20%2a%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22<span style=\"color: #ff0000;\">YHOO<\/span>%22%2C%22<span style=\"color: #ff0000;\">AAPL<\/span>%22%2C%22<span style=\"color: #ff0000;\">GOOG<\/span>%22%2C%22<span style=\"color: #ff0000;\">MSFT<\/span>%22%29%0A%09%09&amp;env=http%3A%2F%2Fdatatables.org%2Falltables.env&amp;format=json<\/a><br \/>\n<strong>Ce qui donne les cotes de Yahoo, \u00a0d&rsquo;Apple et d&rsquo;Amazon et de microsoft.<\/strong><\/p>\n<h2>Les taux de change<\/h2>\n<p><a href=\"http:\/\/finance.yahoo.com\/webservice\/v1\/symbols\/allcurrencies\/quote?format=json\">http:\/\/finance.yahoo.com\/webservice\/v1\/symbols\/allcurrencies\/quote?format=json<\/a><\/p>\n<h2>tou.tv<\/h2>\n<p><a href=\"http:\/\/api.tou.tv\/v1\/toutvapiservice.svc\/json\/GetPageRepertoire\">http:\/\/api.tou.tv\/v1\/toutvapiservice.svc\/json\/GetPageRepertoire<\/a><br \/>\nCe qui donne le r\u00e9pertoire de tou.tv<br \/>\nVoir: \u00a0<a href=\"https:\/\/code.google.com\/p\/tou-tv-for-boxee\/wiki\/Api\">https:\/\/code.google.com\/p\/tou-tv-for-boxee\/wiki\/Api<\/a><\/p>\n<h2>API Apple (iTune, app store, &#8230;)<\/h2>\n<p><a href=\"http:\/\/www.apple.com\/itunes\/affiliates\/resources\/documentation\/itunes-store-web-service-search-api.html\">http:\/\/www.apple.com\/itunes\/affiliates\/resources\/documentation\/itunes-store-web-service-search-api.html<\/a><\/p>\n<h2>GiantBomb (jeux)<\/h2>\n<p><a href=\"http:\/\/www.giantbomb.com\/api\/\">http:\/\/www.giantbomb.com\/api\/<\/a><\/p>\n<hr \/>\n<p style=\"text-align: right;\"><strong><span style=\"color: #003366;\">Document par <a href=\"http:\/\/ve2cuy.wordpress.com\">Alain Boudreault<\/a> (c) 2016-2017<\/span><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00a0Les \u00e9l\u00e9ments de\u00a0comp\u00e9tences de ce laboratoire Savoir utiliser ad\u00e9quatement le protocole &lsquo;Codable&rsquo; -&gt;\u00a0typealias Codable = Decodable &amp; Encodable. Comprendre le r\u00f4le\u00a0des extensions de classes. Savoir\u00a0programmer, en php, \u00a0une API Web proposant des donn\u00e9es selon l&rsquo;approche\u00a0RESTful. Comprendre l&rsquo;utilisation d&rsquo;une API RESTful dans une application Xcode; labo, La pens\u00e9e du jour. Savoir\u00a0analyser une structure de donn\u00e9es json. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3249","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages\/3249","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=3249"}],"version-history":[{"count":0,"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/pages\/3249\/revisions"}],"wp:attachment":[{"href":"https:\/\/ve2cuy.com\/xcode\/wp-json\/wp\/v2\/media?parent=3249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}