<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Evoluation &#187; Blog</title>
	<atom:link href="http://www.evoluation.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.evoluation.com</link>
	<description>The Blog of a Software Engineer</description>
	<lastBuildDate>Mon, 22 Apr 2013 10:19:38 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Syndesmo, l&#8217;échec d&#8217;un projet personnel</title>
		<link>http://www.evoluation.com/blog/2013/04/syndesmo-lechec-dun-projet-personnel/</link>
		<comments>http://www.evoluation.com/blog/2013/04/syndesmo-lechec-dun-projet-personnel/#comments</comments>
		<pubDate>Mon, 22 Apr 2013 06:50:43 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Réflexions]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=812</guid>
		<description><![CDATA[Suite à l’abandon d’un projet personnel qui me tenait à cœur, j’en suis venu à me questionner sur la raison de cet échec, mais aussi les points positifs que j’en ai retenu. Cet article me permet en même temps de clore le dernier chapitre de cette belle aventure. Récapitulatif du projet Le projet commença en [...]]]></description>
				<content:encoded><![CDATA[<p>Suite à l’abandon d’un projet personnel qui me tenait à cœur, j’en suis venu à me questionner sur la <b>raison de cet échec</b>, mais aussi les <b>points positifs </b>que j’en ai retenu. Cet article me permet en même temps de clore le dernier chapitre de cette belle aventure.</p>
<h4>Récapitulatif du projet</h4>
<p><a class="right" href="http://www.evoluation.com/wp-content/uploads/2013/04/logo-syndesmo.png"><img class="size-full wp-image-838 alignright" title="Logo Syndesmo" alt="Logo Syndesmo" src="http://www.evoluation.com/wp-content/uploads/2013/04/logo-syndesmo.png" width="374" height="102" /></a></p>
<p>Le projet commença en Février 2011 à Toulouse, avec mon compère <a href="https://twitter.com/regisTarantini" target="_blank">Régis Tarantini</a>, durant la dernière année de nos études. Notre but au départ était de construire un réseau social Open Source, que chacun puisse installer sur son propre serveur, afin d’avoir la maîtrise totale de ses données.</p>
<p>Nous avons discuté du projet et avons rédigé les spécifications jusqu’en Juin, puis nous avons commencé le développement jusqu’à fin Août, période à laquelle j’ai dû déménager à Bruxelles.</p>
<p>A partir de là, l’avancement du projet aura avancé à tâtons, embûché de longues pauses malgré le recrutement d’un ami designer <a href="https://twitter.com/jeromedieu" target="_blank">Jérôme Dieu</a>, pour finalement se rendre à l’évidence que nous n’étions plus capables d’avancer sur le projet.</p>
<p>Nous y avons donc mis un terme en Novembre dernier, non sans quelques regrets.</p>
<h4>Les raisons de l’échec</h4>
<p>La <b>distance</b> était-elle un problème ? Je ne crois pas, même si ça n’a pas dû jouer en faveur de l’avancement du projet. Des projets Open Source fonctionnent très bien avec des gens aux quatre coins de la planète.</p>
<p>Cependant ce type de projet fonctionne souvent car au moins une des personnes y contribuant s’y consacre à plein temps, ce qui n’était pas notre cas. Nous travaillions sur <b>notre temps personnel</b>, et force est de constater que ce n’est pas chose facile, le travail à distance amenant moins de dynamique. La période coïncidait en même temps avec notre entrée sur le marché du travail, chacun a alors dû revoir ses priorités.</p>
<p>La deuxième raison concerne la <b>taille du projet</b>, il était clairement trop important pour un seul développeur. Nous avons bien sûr reçu quelques propositions de personnes souhaitant nous aider, mais, peut-être par fierté, nous avons refusé ces aides avant de sortir au moins la première version (qui n’aura jamais vu le jour). Peut-être était-ce là notre plus grande erreur…</p>
<p>Une troisième raison selon moi, est d’avoir <b>communiqué trop tôt </b>sur le projet avant de sortir une première version, en créant un site one page de teasing, un blog et une présence sur Facebook et Twitter. Inévitablement, malgré quelques retours positifs à la mise en ligne du site, l’attente des gens s’est essoufflée, et quelque part la nôtre aussi. Car il faut l&rsquo;avouer, travailler aussi longtemps sur un projet sans en sortir la moindre version est assez frustrant.</p>
<p>Enfin, une quatrième raison personnelle qui m’a fait arrêter est le <b>peu de retour budgétaire </b>que l’on aurait pu en tirer, par rapport à notre investissement personnel. Outre la &laquo;&nbsp;gloire&nbsp;&raquo;, nous cherchions évidemment à monétiser le projet afin de, pourquoi pas, créer une structure nous permettant d’en vivre, ce qui n’a malheureusement pas été possible.</p>
<p>J’en profite d’ailleurs pour tirer mon chapeau à tout ceux qui travaillent sur des projets Open Source sans gagner le moindre sous, car on a beau être des rêveurs et vouloir travailler pour la gloire, la réalité est bien là et nous aimons être récompensé pour notre travail (moi le premier !) ou au moins pouvoir en vivre.</p>
<p>C’est pour toutes ces raisons que nous avons décidé d’abandonner le projet à notre grand regret, après avoir pourtant essayé maintes fois d’avancer… Le manque de motivation nous aura finalement rattrapé.</p>
<h4>Les points positifs</h4>
<p>Comme dans tout projet, toute expérience, il y a eu cependant beaucoup d’apports positifs.</p>
<p>Le premier point est juste ce <b>sentiment jouissif de créer son propre produit</b> ! Je ne sais pas si vous l’avez déjà ressenti, mais c’est incroyablement boostant de travailler sur son propre projet, ses propres idées et de se sentir totalement responsable de l’avenir de celui-ci ! Rien que pour cette raison, ça valait la peine de vivre cette expérience et je recommencerais sans hésiter ! Le sentiment d’<b>entreprendre </b>j’imagine…</p>
<p>Le deuxième point qui me vient à l’esprit juste après créer son propre produit, est de pouvoir le faire en <b>collaboration avec un ami</b>. J’ai eu la chance de rencontrer un de mes meilleurs amis à Toulouse et j’ai d’excellents souvenirs de nos soirées passées à rédiger les spécifications du produit, de nos discussions enflammées dans les bouchons du périphérique toulousain, où l’on a l’impression que tout est possible, que chaque nouvelle idée apportée par l’un ou l’autre est génialissime et qu’il n’y a pas de limite à la créativité. On est jeunes, on est beaux (et ben quoi ?) et on a l’avenir devant nous ! Entre nous, qui n’a pas rêvé de créer une start-up à succès et d’aller à San Francisco, hein ? ;-)</p>
<p>Enfin, outre le fait de créer son propre produit, il y a le fait de créer le produit exactement comme on l’imagine, <b>comme si on le faisait pour nous</b>. C’était d’ailleurs mon cas, je n’ai pas de compte Facebook car je suis réticent à exposer ma vie privée à tout le monde, et c’est en partie pour cela que j’ai voulu créer ce réseau social Open Source où j’aurais eu toute confiance en l’endroit où seraient stockées mes données et qui pourrait en faire usage (c’est-à-dire personne).</p>
<h4>Conclusion</h4>
<p>Je suis finalement heureux d’avoir pu participer à ce projet, malgré ses hauts et ses bas.</p>
<p>J&rsquo;en profite d&rsquo;ailleurs pour remercier encore une fois mes compères de m&rsquo;avoir permis de vivre cette aventure. J’en tire beaucoup de conclusions personnelles et professionnelles qui m’aideront à aller de l’avant et à défier de nouveaux challenges.</p>
<p>D’ailleurs je vous laisse, j’ai un nouveau projet qui m’appelle… ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2013/04/syndesmo-lechec-dun-projet-personnel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mise à jour automatique des données en arrière-plan sur iOS</title>
		<link>http://www.evoluation.com/blog/2012/11/mise-a-jour-automatique-des-donnees-en-arriere-plan-sur-ios/</link>
		<comments>http://www.evoluation.com/blog/2012/11/mise-a-jour-automatique-des-donnees-en-arriere-plan-sur-ios/#comments</comments>
		<pubDate>Mon, 12 Nov 2012 12:40:24 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[arrière plan]]></category>
		<category><![CDATA[background update location]]></category>
		<category><![CDATA[didEnterRegion]]></category>
		<category><![CDATA[instapaper]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[mise à jour des données]]></category>
		<category><![CDATA[news.me]]></category>
		<category><![CDATA[update location]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=692</guid>
		<description><![CDATA[Il y a quelques temps, le célèbre développeur Marco Arment proposait une mise à jour de son application Instapaper sur iOS permettant de mettre à jour les données de l&#8217;application en tâche de fond, tout comme l&#8217;application News.me l&#8217;avait fait quelques mois auparavant. Comment cela fonctionne-t-il ? Fonctionnement Comment mettre à jour les données d&#8217;une [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Il y a quelques temps, le célèbre développeur <a title="Marco Arment" href="http://www.marco.org/" target="_blank">Marco Arment</a> proposait une mise à jour de son application <a title="Instapaper" href="http://www.instapaper.com/" target="_blank">Instapaper</a> sur iOS permettant de <a title="Instapaper 4.2.2 with Background Update Locations" href="http://blog.instapaper.com/post/24293729146" target="_blank">mettre à jour les données de l&rsquo;application en tâche de fond</a>, tout comme l&rsquo;application <a title="News.me" href="http://www.news.me/" target="_blank">News.me</a> l&rsquo;avait fait <a title="Introducing Paper Boy: Automatically Download Your News Whenever You Leave Home" href="http://blog.news.me/post/21643399885/introducing-paper-boy-automatically-download-your-news" target="_blank">quelques mois auparavant</a>. Comment cela fonctionne-t-il ?</p>
<h4>Fonctionnement</h4>
<p>Comment mettre à jour les données d&rsquo;une application en tâche de fond alors qu&rsquo;Apple <em>n&rsquo;autorise pas</em> ce comportement ? La solution réside dans l&rsquo;utilisation de la <strong>géolocalisation</strong> et notamment une fonction permettant de <strong>détecter l&rsquo;entrée ou la sortie d&rsquo;une région géographique</strong>, ce que l&rsquo;on appelle le <strong><em>geofencing</em></strong> apparu depuis <strong>iOS 5</strong>. Un évènement peut être levé automatiquement pour ces deux cas, ce qui nous permet ensuite de lancer une requête permettant la récupération de données.</p>
<p>Au niveau du fonctionnement, l&rsquo;utilisateur devra <strong>accepter d&rsquo;utiliser la géolocalisation</strong> et <strong>sauvegarder au moins un point d&rsquo;intérêt</strong> à partir duquel la détection d&rsquo;entrée ou de sortie de région sera mis en place. Un <strong>maximum de dix points d&rsquo;intérêts</strong> simultanés est techniquement accepté par Apple.</p>
<p>A noter qu&rsquo;un autre système fonctionne aussi, qui permet de détecter <strong>n&rsquo;importe quel changement de position</strong>, mais il est beaucoup plus <strong>consommateur de batterie</strong>. L&rsquo;inconvénient de cette méthode est que le GPS tourne en continue, alors que l&rsquo;utilisation de la détection du changement de région n&rsquo;est finalement pas si consommateur que çà.</p>
<p>Le seul désavantage de cette méthode est l&rsquo;utilisation de la géolocalisation et de fait, <strong>son autorisation ou non</strong> par l&rsquo;utilisateur.</p>
<h4>Explication</h4>
<p>L&rsquo;ensemble du code concernant la géolocalisation doit être placé dans l&rsquo;<strong>appDelegate</strong> pour fonctionner.</p>
<h5>1. Ajout du Framework de géolocalisation</h5>
<p>La première étape pour vous permettre d’utiliser la géolocalisation dans votre application est d’ajouter le <strong>Framework CoreLocation</strong>. Pour cela sélectionnez votre « Targets », cliquez sur l’onglet « Build Phases », dépliez « Link Binary With Libraries » et cliquez sur le bouton +.</p>
<p>Ensuite tapez « CoreLocation », sélectionnez le Framework correspondant et cliquez sur « Add ».</p>
<p>Puis, incluez le Framework dans le .h de l&rsquo;appDelegate :</p>
<pre class="wp-code-highlight prettyprint linenums:1">#import &lt;CoreLocation/CoreLocation.h&gt;</pre>
<h5>2. Ajout de l&rsquo;objet CLLocationManager</h5>
<p>Afin de pouvoir utiliser la géolocalisation, vous devez utiliser un objet CLLocationManager. Pour pouvoir utiliser le changement de régions, il doit être déclaré dans l&rsquo;appDelegate. D’abord dans le .h :</p>
<pre class="wp-code-highlight prettyprint linenums:1">@property (strong, nonatomic) CLLocationManager *locationManager;</pre>
<p>Puis dans le .m :</p>
<pre class="wp-code-highlight prettyprint linenums:1">@synthesize locationManager = _locationManager;</pre>
<p>L’appDelegate doit également implémenter le delegate <em>CLLocationManagerDelegate</em> :</p>
<pre class="wp-code-highlight prettyprint linenums:1">@interface AppDelegate : UIResponder &lt;UIApplicationDelegate, CLLocationManagerDelegate&gt;</pre>
<p>Il faut maintenant instancier l&rsquo;objet CLLocationManager dans le constructeur de l&rsquo;appDelegate :</p>
<pre class="wp-code-highlight prettyprint linenums:1">// Instanciate location manager
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;

// Define best location accuracy
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;</pre>
<h5>3. Ajouter une région à surveiller</h5>
<p>Pour ajouter une région à surveiller, Apple fournit <a href="http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW1" title="Documentation Apple" target="_blank">un exemple de code dans sa documentation</a> qui convient très bien. Ajoutons donc cette méthode dans l’appDelegate :</p>
<pre class="wp-code-highlight prettyprint linenums:1">- (BOOL)registerRegionWithCircularOverlay:(MKCircle *)overlay andIdentifier:(NSString *)identifier
{
    // Do not create regions if support is unavailable or disabled.
    if ( ![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] )
        return NO;

    // If the radius is too large, registration fails automatically,
    // so clamp the radius to the max value.
    CLLocationDegrees radius = overlay.radius;

    if (radius &gt; self.locationManager.maximumRegionMonitoringDistance)
        radius = self.locationManager.maximumRegionMonitoringDistance;

    // Create the region and start monitoring it.
    CLRegion* region = [[CLRegion alloc] initCircularRegionWithCenter:overlay.coordinate radius:radius identifier:identifier];
    [self.locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];

    return YES;
}</pre>
<h5>4. Surveiller les changements de régions</h5>
<p>Avant d’appeler la méthode <em>registerRegionWithCircularOverlay:andIdentifier:</em> définit ci-dessus, il faut implémenter deux méthodes du CLLocationManagerDelegate, qui permettent respectivement de détecter <strong>l’entrée</strong> et <strong>la sortie</strong> d’une région :</p>
<pre class="wp-code-highlight prettyprint linenums:1">- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@&quot;locationManager didEnterRegion for %@&quot;, region.identifier);
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@&quot;locationManager didExitRegion for %@&quot;, region.identifier);
}</pre>
<p>C’est à l’intérieur de ces méthodes qu’il faudra lancer la requête, permettant de récupérer les derniers tweets par exemple.</p>
<p>La dernière chose à faire est d’ajouter une région à surveiller. Pour l’exemple nous l’ajouterons dans l’appDelegate au sein de la méthode <em>application:didFinishLaunchingWithOptions:</em> :</p>
<pre class="wp-code-highlight prettyprint linenums:1">// Example: Apple location
CLLocationCoordinate2D coord;
coord.latitude =  37.332409;
coord.longitude = -122.030512

CLLocationDistance dist = 1.0;

MKCircle *circle = [MKCircle circleWithCenterCoordinate:coord radius:dist];

[self registerRegionWithCircularOverlay:circle andIdentifier:@&quot;MyRegion&quot;];</pre>
<p>A tout moment, il est possible de consulter les régions à surveiller en mémoire (pour rappel, le SDK ne nous permet d&rsquo;en enregistrer que <em>dix simultanément</em>).</p>
<pre class="wp-code-highlight prettyprint linenums:1">NSLog(@&quot;%@&quot;, self.locationManager.monitoredRegions);</pre>
<h5>5. Lancer une requête</h5>
<p>Il ne reste plus qu’à lancer une requête Web à l’intérieur des méthodes <em>didEnterRegion</em> et / ou <em>didExitRegion</em>.</p>
<p>Tout dépend de la fonction de votre application, on peut imaginer que vous vouliez mettre votre flux d&rsquo;actualités à jour par exemple.</p>
<h5>6. Tester</h5>
<p>Le <strong>simulateur</strong> nous permet de tester cette méthode, en allant dans le menu &laquo;&nbsp;Débogage&nbsp;&raquo;, puis &laquo;&nbsp;Lieu&nbsp;&raquo;.</p>
<p>En partant de mon exemple où j&rsquo;ai enregistré la position du siège d&rsquo;Apple à Cupertino, pour déclencher <strong>la sortie de la région</strong>, il faut entrer <em>un lieu personnalisé</em>, par exemple 37 en latitude et -122 en longitude.<br />
Puis pour déclencher <strong>l&rsquo;entrée dans la région</strong> enregistrée, il faudra sélectionner &laquo;&nbsp;<em>Apple</em>&nbsp;&raquo; dans la liste des lieux qui sont disponibles au sein du menu.</p>
<p>Concernant les <strong>iDevices</strong>, cela ne fonctionne que sur un <strong>iPhone 4 ou supérieur</strong> ou <strong>iPad 2 ou supérieur</strong> qui soient des <em>modèles 3G</em>, puisque la manipulation requiert une puce GPS.</p>
<p>Je vous conseille d&rsquo;enregistrer votre <strong>lieu courant</strong>, puis de tester en laissant d&rsquo;abord votre application <em>ouverte</em> pour voir la distance qu&rsquo;il est nécessaire de parcourir pour que l&rsquo;évènement se déclenche, puis de refaire le test avec l&rsquo;application <em>fermée</em>.</p>
<p>Lors de mes tests, j&rsquo;ai dû marcher environ 150 mètres&#8230; ;-)</p>
<h4>Conclusion</h4>
<p>L&rsquo;utilisation de cette méthode revient au final plus à un <em>hack</em> qu&rsquo;à une prouesse technique. Malheureusement Apple n&rsquo;autorisant pas les requêtes en tâches de fond, c&rsquo;est pour l&rsquo;instant le seul moyen connu d&rsquo;y avoir recours. N&rsquo;hésitez pas à réagir dans les commentaires sur vos propres tests (<em>et votre distance parcourue&#8230; à pied bien sûr</em>) !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/11/mise-a-jour-automatique-des-donnees-en-arriere-plan-sur-ios/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Internationaliser son site Web avec Silex et le composant Translation</title>
		<link>http://www.evoluation.com/blog/2012/06/internationaliser-son-site-web-avec-silex-et-le-composant-translation/</link>
		<comments>http://www.evoluation.com/blog/2012/06/internationaliser-son-site-web-avec-silex-et-le-composant-translation/#comments</comments>
		<pubDate>Tue, 26 Jun 2012 06:50:55 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[bundle]]></category>
		<category><![CDATA[internationaliser]]></category>
		<category><![CDATA[multi-langue]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[silex]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[traduction]]></category>
		<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=598</guid>
		<description><![CDATA[Le célèbre Framework PHP Symfony2 est construit de telle sorte, que chaque brique du Framework peut fonctionner de manière autonome en étant répartis dans ce qu’on appelle des composants, réutilisables à souhait dans n’importe quel autre projet. C’est le cas du Framework Silex, développé lui aussi par Fabien Potencier, le créateur de Framework Symfony, et [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Le célèbre <a title="Symfony2" href="http://symfony.com/" target="_blank">Framework PHP Symfony2</a> est construit de telle sorte, que chaque brique du Framework peut fonctionner de manière autonome en étant répartis dans ce qu’on appelle des <em><strong>composants</strong></em>, réutilisables à souhait dans n’importe quel autre projet. C’est le cas du <a title="Silex" href="http://silex.sensiolabs.org/" target="_blank">Framework Silex</a>, développé lui aussi par <a title="Blog de Fabien Potencier" href="http://fabien.potencier.org/" target="_blank">Fabien Potencier</a>, le créateur de Framework Symfony, et <a href="http://twitter.com/igorwesome">Igor Wiedler</a>, qui reprend les classes de base de Symfony2 pour en faire un micro-Framework. Voyons ensemble comment ajouter un composant de Symfony2 au Framework Silex : <strong>le composant Translation</strong>.</p>
<h4>Installation de Silex</h4>
<p>Concernant l’installation de Silex, je vous renvoie vers mon précédent article traitant de l’<a title="Installer et utiliser Composer en PHP" href="http://www.evoluation.com/blog/2012/06/installer-et-utiliser-composer-en-php/">installation de bibliothèque PHP avec Composer</a>. La <a title="Documentation officielle de Silex pour l'installation" href="http://silex.sensiolabs.org/doc/usage.html" target="_blank">documentation officielle de Silex</a> pourra aussi vous aider.</p>
<h4>Ajout du composant Translation</h4>
<p>L’ajout du composant Translation peut se faire de plusieurs manières, mais la plus simple et la plus rapide est sans nul doute d’utiliser <strong>Composer</strong>, en ajoutant cette ligne dans le fichier composer.json :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&quot;symfony/translation&quot;: &quot;2.1.*&quot;</pre>
<p>Lancez ensuite l’installation via la ligne de commande de Composer (<a title="Installer et utiliser Composer en PHP" href="http://www.evoluation.com/blog/2012/06/installer-et-utiliser-composer-en-php/">voir mon article sur l’utilisation de Composer</a>).</p>
<p>Une fois le composant Translation téléchargé, il faut s’y <em>abonner</em> dans le fichier index.php, en ajoutant ce code PHP :</p>
<pre class="wp-code-highlight prettyprint linenums:1">$app-&gt;register(new Silex\Provider\TranslationServiceProvider(), array(
    &#039;locale_fallback&#039; =&gt; &#039;en&#039;,
));</pre>
<p>Le paramètre <strong>locale_fallback</strong> est facultatif, il vous permet de définir la langue par défaut.</p>
<h4>Création des fichiers de traduction</h4>
<p>Plutôt que de mettre toutes les traductions en dur dans le fichier index.php, nous avons la possibilité de les <em>externaliser dans des fichiers YAML</em>.</p>
<p>A la suite du code ajouté précédemment dans le fichier index.php, ajoutez le code suivant :</p>
<pre class="wp-code-highlight prettyprint linenums:1">use Symfony\Component\Translation\Loader\YamlFileLoader;

$app[&#039;translator&#039;] = $app-&gt;share($app-&gt;extend(&#039;translator&#039;, function($translator, $app) {
    $translator-&gt;addLoader(&#039;yaml&#039;, new YamlFileLoader());

    // Ajout des fichiers de ressources de langue
    $translator-&gt;addResource(&#039;yaml&#039;, __DIR__.&#039;/locales/en.yml&#039;, &#039;en&#039;);
    $translator-&gt;addResource(&#039;yaml&#039;, __DIR__.&#039;/locales/fr.yml&#039;, &#039;fr&#039;);

    return $translator;
}));</pre>
<p>Vous pouvez ajouter autant de fichier de langues que vous le souhaitez. Le contenu de ces fichiers doit respecter la syntaxe YAML (<em>indentation à l&rsquo;aide de deux espaces, pas de tabulation</em>), ce qui ressemble à ceci :</p>
<pre class="wp-code-highlight prettyprint linenums:1">cle: valeur
  cle_placeholder: valeur %placeholder%</pre>
<p>La clé vous permettra d’appeler la traduction, avec la possibilité d’utiliser un <strong>placeholder</strong> si besoin. A noter qu’il est possible d’<strong>imbriquer des clés</strong> dans le fichier YAML, ce qui permet d’éviter de se répéter :</p>
<pre class="wp-code-highlight prettyprint linenums:1">cle :
  sous_cle : ma valeur</pre>
<p>Cela donnera à l’utilisation <strong>cle.sous_cle</strong> pour afficher <strong>ma valeur</strong>.</p>
<h4>Gérer les URLs</h4>
<p>Afin d&rsquo;avoir de belles URLs, peu importe la langue sélectionnée, Silex incorpore tout ce qu&rsquo;il faut.</p>
<h5>1. Dans les contrôleurs</h5>
<p>Prenons l&rsquo;exemple de la page d&rsquo;accueil, dont le contrôleur se présente comme ceci dans le fichier index.php :</p>
<pre class="wp-code-highlight prettyprint linenums:1">$app-&gt;get(&#039;/{_locale}&#039;, function() use ($app) {
    return $app[&#039;twig&#039;]-&gt;render(&#039;homepage.twig&#039;);
})
-&gt;assert(&#039;_locale&#039;, &#039;fr|nl&#039;)
-&gt;value(&#039;_locale&#039;, &#039;fr&#039;)
-&gt;bind(&#039;homepage&#039;);</pre>
<p>Plusieurs choses ici :</p>
<ol>
<li>Le placeholder <strong>_locale</strong> est <em>facultatif</em>, si nous voulons y avoir accès, il est doit être placé en paramètre,</li>
<li>A l&rsquo;aide de la méthode <strong>assert()</strong>, nous forçons le paramètre <strong>_locale</strong> à avoir la valeur soit <strong>fr</strong>, soit <strong>en</strong>,</li>
<li>La méthode <strong>value()</strong> permet de rendre le paramètre <strong>_locale</strong> facultatif en lui donnant la valeur <strong>fr</strong> si aucune valeur n&rsquo;est passée. Ainsi nous pourrons accéder à l&rsquo;URL de cette manière : http://monsite.com/fr et http://monsite.com,</li>
</ol>
<p>Nous pouvons aussi bien sûr rallonger l&rsquo;URL, ce qui pourrait donner :</p>
<pre class="wp-code-highlight prettyprint linenums:1">$app-&gt;get(&#039;/{_locale}/contact&#039;, function() use ($app) { ... }</pre>
<p>De cette manière, on pourrait accéder à l&rsquo;URL http://monsite.com/fr/contact ou bien http://monsite.com/en/contact.</p>
<p><strong><em>Nota</em></strong> : le fait d&rsquo;accéder à une URL avec la langue passée dans l&rsquo;URL <em>modifie automatiquement la langue courante du site</em>.</p>
<h5>2. Dans les vues</h5>
<p>Pour récupérer la langue courante dans une vue avec Twig, il suffit d&rsquo;appeler le helper suivant : <strong>app.request.locale</strong>. Typiquement, pour l&rsquo;URL de contact définie ci-dessus, cela donnerait :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;a href=&quot;{{ path(&#039;contact&#039;, {&#039;_locale&#039;: app.request.locale}) }}&quot;&gt;&lt;/a&gt;</pre>
<p>Nous passons la langue définie en paramètre au helper <strong>path()</strong> qui va générer l&rsquo;URL définitive. Si nous voulions changer la langue courante, il suffirait de forcer le paramètre <strong>_locale</strong>, par exemple :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;a href=&quot;{{ path(&#039;contact&#039;, {&#039;_locale&#039;: &#039;fr&#039;}) }}&quot;&gt;&lt;/a&gt;</pre>
<p>C&rsquo;est ce que nous utiliserons typiquement comme lien pour changer la langue du site.</p>
<h4>Accès à une traduction</h4>
<p>Maintenant que nous avons défini la <strong>langue courante</strong>, nous pouvons accéder aux <strong>traductions</strong>, soit dans le contrôleur directement, soit la plupart du temps dans les vues (templates Twig).</p>
<h5>1. Accéder à une traduction depuis un contrôleur</h5>
<p>La syntaxe pour accéder à une traduction dans un contrôleur est la suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">$app[&#039;translator&#039;]-&gt;trans(&#039;cle&#039;);</pre>
<p>Si nous voulons accéder à une traduction à l&rsquo;aide d&rsquo;un placeholder, il faut simplement rajouter un tableau contenant le ou les placeholders :</p>
<pre class="wp-code-highlight prettyprint linenums:1">$app[&#039;translator&#039;]-&gt;trans(&#039;sous_cle&#039;, array(&#039;%name%&#039; =&gt; &#039;Nicolas&#039;));</pre>
<h5>2. Accéder à une traduction depuis un template Twig</h5>
<p>La syntaxe pour accéder à une traduction dans une vue avec Twig est la suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">{{ app.translator.trans(&#039;cle&#039;) }}</pre>
<p>Si nous voulons accéder à une traduction à l&rsquo;aide d&rsquo;un placeholder, il faut là aussi rajouter un tableau contenant le ou les placeholders :</p>
<pre class="wp-code-highlight prettyprint linenums:1">{{ app.translator.trans(&#039;sous_cle&#039;, {&#039;%name%&#039; =&gt; &#039;Nicolas&#039;}) }}</pre>
<h4>Générer les URLs selon la langue courante</h4>
<p>Lorsque vous avez un site multi-langue et que vous souhaitez <strong>générer automatiquement l&rsquo;URL de changement de langue avec la page courante</strong>, vous allez être confronté à un problème : <em>comment modifier l&rsquo;URL de la page courante pour lui passer la nouvelle langue ?</em></p>
<p>Sur la page de contact par exemple, ou sur n&rsquo;importe quelle autre, nous souhaiterions avoir les URLs suivantes :</p>
<ul>
<li>http://monsite.com/fr/contact</li>
<li>http://monsite.com/en/contact</li>
<li>http://monsite.com/it/contact</li>
</ul>
<p>Comment peut-on générer <em>automatiquement</em> ces URLs dans les vues ? Tout simplement en récupérant le <strong>nom de la route courante</strong>, pour pouvoir regénérer l&rsquo;URL courante avec la langue de notre choix, ce qui donne :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;a href=&quot;{{ path(app.request.get(&#039;_route&#039;), {&#039;_locale&#039;: &#039;fr&#039;}) }}&quot;&gt;FR&lt;/a&gt;</pre>
<p>L&rsquo;astuce réside dans l&rsquo;appel du helper qui contient le nom de la route courante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">app.request.get(&#039;_route&#039;)</pre>
<h4>Conclusion</h4>
<p>Comme vous avez pu le voir, l&rsquo;intérêt des <strong>composants dans Symfony2</strong> est réel. Nous avons pu intégrer le composant Translation très facilement, que ce soit dans les contrôleurs ou les vues avec le moteur de template Twig.</p>
<p>Et vous, utilisez-vous les composants de Symfony2 dans vos projets ?</p>
<p><span style="color: #999"><em>Si vous voulez en savoir plus à propos du composant Translation, vous pouvez consulter les documentations de Symfony2 et Silex à ce sujet :</em></span></p>
<ul>
<li><a title="Documentation Symfony2 sur le composant Translation" href="http://symfony.com/doc/current/book/translation.html" target="_blank">http://symfony.com/doc/current/book/translation.html</a></li>
<li><a title="Documentation Silex sur le composant Translation" href="http://silex.sensiolabs.org/doc/providers/translation.html" target="_blank">http://silex.sensiolabs.org/doc/providers/translation.html</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/06/internationaliser-son-site-web-avec-silex-et-le-composant-translation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Installer et utiliser Composer en PHP</title>
		<link>http://www.evoluation.com/blog/2012/06/installer-et-utiliser-composer-en-php/</link>
		<comments>http://www.evoluation.com/blog/2012/06/installer-et-utiliser-composer-en-php/#comments</comments>
		<pubDate>Thu, 21 Jun 2012 19:57:47 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[bibliothèques]]></category>
		<category><![CDATA[composer]]></category>
		<category><![CDATA[mamp]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[silex]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=508</guid>
		<description><![CDATA[Tout comme Nuget pour le language .Net, PHP possède quelques installateurs de bibliothèques, qui installent vos bibliothèques préférées pour vous, tout en gérant les dépendances. L&#8217;un d&#8217;entre eux est Composer, comment fonctionne-t-il ? Installation La première chose à faire est de télécharger le fichier composer.phar qui permet ensuite de télécharger les bibliothèques PHP. Ouvrez le [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Tout comme <a title="L’installateur de bibliothèque .Net pour Visual Studio : Nuget" href="http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/">Nuget pour le language .Net</a>, PHP possède quelques installateurs de bibliothèques, qui installent vos bibliothèques préférées pour vous, tout en gérant les dépendances. L&rsquo;un d&rsquo;entre eux est <a title="Composer" href="http://getcomposer.org/" target="_blank">Composer</a>, comment fonctionne-t-il ?</p>
<h4>Installation</h4>
<p>La première chose à faire est de télécharger le fichier <strong>composer.phar</strong> qui permet ensuite de télécharger les bibliothèques PHP. Ouvrez le Terminal, placez-vous dans le dossier de votre projet où les fichiers sources seront téléchargés et tapez la ligne de commande suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">curl -s http://getcomposer.org/installer | php</pre>
<p>Pour les <strong>utilisateurs de Windows</strong>, si <strong>Curl</strong> n&rsquo;est pas installé sur votre machine, vous trouverez les instructions d&rsquo;installation ici (<em>en anglais</em>) : <a href="http://getcomposer.org/download/." title="Installer Curl" target="_blank">http://getcomposer.org/download/</a>.</p>
<p>La solution la plus simple est de taper la ligne de commande suivante dans le terminal, qui a pour effet de vérifier la configuration du fichier php.ini et de lancer le téléchargement du fichier composer.phar si tout va bien :</p>
<pre class="wp-code-highlight prettyprint linenums:1">php -r &quot;eval(&#039;?&gt;&#039;.file_get_contents(&#039;https://getcomposer.org/installer&#039;));&quot;</pre>
<p>Cependant quelques erreurs peuvent apparaître à ce niveau-ci :</p>
<ol>
<li><strong>&laquo;&nbsp;&lsquo;php&rsquo; n&rsquo;est pas reconnu en tant que commande interne ou externe, un programme exécutable ou un fichier de commandes.&nbsp;&raquo;</strong> : dans la ligne de commande, il faut spécifier le chemin complet du dossier où est installé PHP sur votre machine. Par exemple :
<pre class="wp-code-highlight prettyprint linenums:1">C:\wamp\bin\php\php5.3.13\php -r &quot;eval(&#039;?&gt;&#039;.file_get_contents(&#039;https://getcomposer.org/installer&#039;));&quot;</pre>
</li>
<li><strong>&laquo;&nbsp;PHP Warning:  file_get_contents(): Unable to find the wrapper &laquo;&nbsp;https&nbsp;&raquo; &#8211; did you forget to enable it when you configured PHP?&nbsp;&raquo;</strong> : l&rsquo;option SSL n&rsquo;est pas activé dans votre fichier php.ini (situé dans le répertoire d&rsquo;installation de PHP). Il suffit de l&rsquo;ouvrir puis de retirer le point virgule devant cette ligne, d&rsquo;enregistrer le fichier, puis de redémarrer WAMP :
<pre class="wp-code-highlight prettyprint linenums:1">extension=php_openssl.dll</pre>
</li>
</ol>
<h4>Configuration</h4>
<p>Il est important de noter que vous aurez besoin du fichier composer.phar pour <strong>chaque projet</strong> avec lequel vous utiliserez Composer et que celui-ci doit se placer à la <strong>racine</strong> de vos projets.</p>
<p>Il faut maintenant configurer la liste des bibliothèques que nous voulons télécharger. Cela se fait par la création d&rsquo;un fichier qui doit être nommé <strong>composer.json</strong> et qui doit contenir l&rsquo;<em>ensemble des bibliothèques PHP que nous souhaitons installer</em>. On peut par exemple vouloir installer le <a title="Silex" href="http://silex.sensiolabs.org/" target="_blank">projet Open Source Silex</a> :</p>
<pre class="wp-code-highlight prettyprint linenums:1">{
    &quot;minimum-stability&quot;: &quot;dev&quot;,
    &quot;require&quot;: {
        &quot;silex/silex&quot;: &quot;1.0.*&quot;
    }
}</pre>
<h4>Téléchargement des bibliothèques</h4>
<p>Maintenant que nous avons téléchargé et configuré Composer, nous n&rsquo;avons plus qu&rsquo;à lancer le <strong>téléchargement</strong> des différentes bibliothèques. Pour cela, il suffit de taper la ligne de commande suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">php composer.phar install</pre>
<p>Par la suite, si une ou plusieurs mises à jour de bibliothèques sont disponibles, il est possible de les mettre à jour en tapant la ligne de commande suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">php composer.phar update</pre>
<p>Les bibliothèques sont téléchargées dans un dossier <strong>vendor</strong> automatiquement créé à la racine du projet, avec en plus un fichier <strong>autoload.php</strong> à inclure dans le fichier source principal de votre projet, qui permet de charger automatiquement chaque classe se trouvant dans le dossier <strong>vendor</strong>.</p>
<p>Enfin, un fichier <strong>composer.lock</strong> est également créé, il contient la liste des bibliothèques installées ainsi que leur version.</p>
<h4>Gestion des erreurs</h4>
<p>Lors de l&rsquo;installation de Composer, vous pouvez être confronté à deux erreurs :</p>
<ol>
<li><strong>Git doit être installé sur votre ordinateur</strong> : ce problème est simple à régler, il suffit de télécharger le logiciel Git à cette adresse : <a title="Git" href="http://git-scm.com/" target="_blank">http://git-scm.com/</a> et de l&rsquo;installer.</li>
<li><strong>La variable detect_unicode du php.ini doit être à Off</strong> : pour régler ce problème, il faut aller dans le fichier <strong>php.ini</strong> et affecter la valeur <strong>Off</strong> à la variable <strong>detect_unicode</strong>.</li>
</ol>
<p><em><strong>Nota</strong></em> : si vous êtes sous <em>OS X</em> et que vous utilisez <em>MAMP</em>, le fait de modifier le fichier php.ini dans le répertoire suivant ne résoudra en rien votre problème :</p>
<pre class="wp-code-highlight prettyprint linenums:1">/Applications/MAMP/bin/php/php5.x.x/conf/php.ini</pre>
<p>La solution est de créer un fichier <strong>php.ini</strong> dans le répertoire <strong>/etc</strong>. Il vous faudra alors les <strong>droits administrateurs</strong> pour pouvoir enregistrer vos modifications. Le plus simple est de taper la commande suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">sudo nano /etc/php.ini</pre>
<p>Entrez votre mot de passe, puis écrivez dans le fichier php.ini :</p>
<pre class="wp-code-highlight prettyprint linenums:1">detect_unicode = Off</pre>
<p>Enregistrez, redémarrez MAMP et le tour est joué ! ;-)</p>
<h4>Exemple d&rsquo;utilisation : création d&rsquo;un projet Silex</h4>
<p>De gros projets sont maintenant gérés par Composer, tels que <a title="Symfony2" href="http://symfony.com/" target="_blank">Symfony2</a> ou encore <a title="Silex" href="http://silex.sensiolabs.org/" target="_blank">Silex</a>. Voici un exemple d&rsquo;installation d&rsquo;un <strong>nouveau projet Silex</strong> :</p>
<h5>1. Création d&rsquo;un nouveau dossier</h5>
<p>Commençons par créer un nouveau dossier qui contiendra notre nouveau projet, appelons-le <em>SilexProject</em>.</p>
<h5>2. Téléchargement du fichier composer.phar</h5>
<p>Ensuite, nous devons télécharger le fichier <strong>composer.phar</strong> dans ce dossier, à l&rsquo;aide de la ligne de commande suivante :</p>
<pre class="wp-code-highlight prettyprint linenums:1">curl -s http://getcomposer.org/installer | php</pre>
<h5>3. Création du fichier composer.json</h5>
<p>Créons maintenant notre fichier nommé <strong>composer.json</strong> qui contiendra les bibliothèques que nous voulons télécharger :</p>
<pre class="wp-code-highlight prettyprint linenums:1">{
    &quot;minimum-stability&quot;: &quot;dev&quot;,
    &quot;require&quot;: {
        &quot;silex/silex&quot;: &quot;1.0.*&quot;,
        &quot;symfony/translation&quot;: &quot;2.1.*&quot;,
        &quot;symfony/config&quot;: &quot;2.1.*&quot;,
        &quot;symfony/yaml&quot;: &quot;2.1.*&quot;,
        &quot;twig/twig&quot;: &quot;&gt;=1.8,&lt;2.0-dev&quot;
    }
}</pre>
<p>J&rsquo;ai rajouté le composant <a title="Translation" href="https://github.com/symfony/Translation" target="_blank"><strong>Translation</strong></a> permettant de gérer l&rsquo;<em>internationalisation</em> d&rsquo;un projet, ainsi que le <em>moteur de template</em> <a title="Twig" href="http://twig.sensiolabs.org/" target="_blank"><strong>Twig</strong></a>.</p>
<h5>4. Téléchargement des bibliothèques</h5>
<p>Lançons maintenant le téléchargement des bibliothèques grâce à la ligne de commande suivante dans le Terminal (<em>en s&rsquo;étant au préalable déplacé dans le dossier du projet</em>) :</p>
<pre class="wp-code-highlight prettyprint linenums:1">php composer.phar install</pre>
<p><strong><em>Nota</em></strong> : à cette étape, il est possible que vous rencontriez un souci avec Composer si vous étiez parti d&rsquo;une version de Silex <em>directement téléchargée à partir de leur site</em>. Il est conseillé de partir d&rsquo;un projet vierge comme je le fais pour éviter tout problème.</p>
<h5>5. Création du fichier de bootstrap Silex</h5>
<p>Tout est prêt, nous n&rsquo;avons plus qu&rsquo;à créer notre fichier boostrap pour faire fonctionner Silex dans une page Web. Pour cela créons un fichier <strong>index.php</strong>, dans un sous-dossier appelé <strong>web</strong> :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;?php

// Inclusion du fichier autoload.php permettant de charger automatiquement les bibliothèques
require_once __DIR__.&#039;/../vendor/autoload.php&#039;;

$app = new Silex\Application();

$app-&gt;get(&#039;/&#039;, function () use ($app) {
    return &#039;Hello world!&#039;;
});

$app-&gt;run();</pre>
<p>Notre application est fonctionnelle ! :-)</p>
<h4>Conclusion</h4>
<p><strong>Composer</strong> est un outil très pratique, qui vous permet d&rsquo;installer votre environnement de travail en <em>très peu de temps</em> et en vous garantissant l&rsquo;<em>intégrité des bibliothèques téléchargées</em>, grâce à la gestion des dépendances. Et vous, utilisez-vous Composer ?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/06/installer-et-utiliser-composer-en-php/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Protocol &amp; delegate : un puissant Design Pattern</title>
		<link>http://www.evoluation.com/blog/2012/05/protocol-delegate-un-puissant-design-pattern/</link>
		<comments>http://www.evoluation.com/blog/2012/05/protocol-delegate-un-puissant-design-pattern/#comments</comments>
		<pubDate>Sun, 27 May 2012 15:38:11 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Design Pattern]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[delegate]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[mettre à jour]]></category>
		<category><![CDATA[protocol]]></category>
		<category><![CDATA[viewcontroller]]></category>
		<category><![CDATA[vue]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=420</guid>
		<description><![CDATA[Lors du développement d&#8217;une application iOS, il est très fréquent d&#8217;utiliser plusieurs vues. Bien souvent même, une seconde vue est chargée en plus de la première vue qui est restée en mémoire, et on veut mettre à jour la première vue suite aux modifications apportées dans la seconde vue. On se retrouve alors face à [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Lors du développement d&rsquo;une application iOS, il est très fréquent d&rsquo;utiliser <strong>plusieurs vues</strong>. Bien souvent même, une seconde vue est chargée en plus de la première vue qui est restée en mémoire, et on veut mettre à jour la première vue suite aux modifications apportées dans la seconde vue. On se retrouve alors face à une problématique : <em>comment avertir la classe appelante à partir de la classe appelée</em> ? Et surtout, comment éviter de trop <em>coupler nos objets</em> ?</p>
<h4>Etude de cas : gestionnaire de tâches</h4>
<p>Prenons le cas simple d&rsquo;un gestionnaire de tâches (*). Nous avons une première vue nommée <em>ListTaskViewController</em> qui contient une liste des tâches, et une seconde vue nommée <em>AddTaskViewController</em> permettant d&rsquo;ajouter une tâche dans cette liste.</p>
<p style="text-align: center;"><a href="http://www.evoluation.com/wp-content/uploads/2012/05/schema.png" target="_blank"><img class="aligncenter  wp-image-427" title="Exemple d'application iOS à deux vues" src="http://www.evoluation.com/wp-content/uploads/2012/05/schema.png" alt="Exemple d'application iOS à deux vues" width="640" height="433" /></a></p>
<p>La question que l&rsquo;on se pose est : comment <strong>mettre à jour</strong> le UITableView de la première vue suite à l&rsquo;<strong>ajout d&rsquo;une tâche</strong> dans la seconde vue ?</p>
<h4>Fonctionnement des vues</h4>
<p>Dans notre exemple, la première vue qui contient une liste des tâches possède un bouton permettant d&rsquo;ajouter une tâche. Au clic sur celui-ci, la première vue <strong>instancie</strong> et <strong>affiche</strong> la seconde vue qui contient le formulaire d&rsquo;ajout d&rsquo;une tâche.</p>
<p>C&rsquo;est donc la <em>première vue qui interagit sur la seconde</em> et non pas l&rsquo;inverse. Or comment la seconde vue peut avertir la première vue qu&rsquo;une nouvelle tâche vient d&rsquo;être ajoutée ?</p>
<h4>L&rsquo;objet delegate</h4>
<p>Plusieurs solutions plus ou moins <em>catholiques</em> sont possibles, mais la plus respectueuse des standards est sans nul doute l&rsquo;utilisation d&rsquo;un<strong> delegate</strong>, qui va gérer l&rsquo;évènement d&rsquo;<em>ajout d&rsquo;une tâche</em>, pour <strong>prévenir</strong> la première vue de se <strong>mettre à jour</strong> et ainsi afficher la nouvelle tâche fraichement ajoutée.</p>
<p><em>Qu&rsquo;est-ce qu&rsquo;un delegate</em> ? C&rsquo;est tout simplement une <strong>instance de classe</strong>. Dans notre exemple, l&rsquo;instance de la classe ListTaskViewController sera contenu dans une <strong>propriété</strong> de la classe AddTaskViewController que l&rsquo;on appellera delegate.</p>
<h4>Notion de POO : l&rsquo;interface</h4>
<p>Avant d&rsquo;aller plus loin et de vous parler du <strong>protocol</strong>, il est nécessaire de connaître et de comprendre une notion très importante quand on parle de programmation orientée objet : <a title="Interface (programmation orientée objet)" href="http://fr.wikipedia.org/wiki/Interface_(programmation_orientée_objet)" target="_blank">l&rsquo;<strong>interface</strong></a>.</p>
<p>Une interface est un <em>ensemble de déclarations de méthodes</em> publiques ou privés. Lorsqu&rsquo;une classe implémente une interface, elle doit <strong>implémenter ses méthodes</strong>.</p>
<h4>L&rsquo;équivalent Objective-C : le protocol</h4>
<p>L&rsquo;équivalent d&rsquo;une interface en Objective-C est-ce qu&rsquo;on appelle un <strong>protocol</strong>. Attention, le protocol rajoute une option supplémentaire : alors que les méthodes d&rsquo;interfaces sont normalement obligatoires à implémenter, il est possible de spécifier des <em>méthodes optionnels</em> en Objective-C.</p>
<h4>Mise en pratique</h4>
<p>Le but va donc être de suivre le processus suivant :</p>
<ol>
<li><strong>Créer un protocol</strong> dans la classe AddTaskViewController, contenant une méthode qui indiquera qu&rsquo;une tâche vient d&rsquo;être ajouté,</li>
<li><strong>Appeler la méthode du protocol</strong> dans la classe AddTaskViewController, lorsque l&rsquo;utilisateur ajoutera une nouvelle tâche,</li>
<li><strong>Implémenter ce protocol</strong> dans la classe ListTaskViewController, ce qui nous permettra d&rsquo;être avertit lorsque sa méthode sera appelée.</li>
</ol>
<p>Un bon exemple valant mieux qu&rsquo;un long discours, mettons cela en pratique.</p>
<h5>1. Déclaration du protocol dans la classe AddTaskViewController</h5>
<pre class="wp-code-highlight prettyprint linenums:1">#import 

// Déclaration du protocol en haut de la classe,
// pour rendre son type accessible dans la propriété delegate
@protocol AddTaskDelegate;

@interface AddTaskViewController : UIViewController {
    // ...
}

// Déclaration de la propriété delegate,
// qui est un objet devant implémenter le protocol AddTaskDelegate
@property (nonatomic, assign) id&lt;AddTaskDelegate&gt; delegate;

// ...

@end

///////////////////////////////////////////////////////////////////

// Déclaration du protocol
@protocol AddTaskDelegate &lt;NSObject&gt;

// Indique que la méthode doit obligatoirement être implémentée
// (si elle peut être implémentée, le mot clé est @optional)
@required

// Méthode appelée lors de l&#039;ajout d&#039;une tâche,
// son nom est passé en paramètre
- (void)taskDidAdd:(NSString *)name;

@end</pre>
<h5>2. Appel de la méthode du protocol dans la classe AddTaskViewController</h5>
<pre class="wp-code-highlight prettyprint linenums:1">- (IBAction)add:(id)sender
{
    // ...

    // On vérifie que la méthode du protocol est bien implémentée
    // dans l&#039;objet delegate (ici ListTaskViewController)
    if ([_delegate respondsToSelector:@selector(taskDidAdd:)]) {
        // La méthode est appelée avec le nom de la tâche en paramètre
        [_delegate taskDidAdd:_nameTextField.text];
    }

    // ...
}</pre>
<h5>3. Implémentation du protocol dans la classe ListTaskViewController</h5>
<p>Dans le fichier .h</p>
<pre class="wp-code-highlight prettyprint linenums:1">@interface ListTaskViewController : UIViewController
    &lt;UITableViewDataSource, AddTaskDelegate&gt; {
    // ...
}</pre>
<p>Dans fichier le .m</p>
<pre class="wp-code-highlight prettyprint linenums:1">// Instanciation de l&#039;objet AddTaskViewController au clic
// sur le bouton d&#039;ajout d&#039;une tâche
- (IBAction)addTask:(id)sender
{
    AddTaskViewController *viewController = [[AddTaskViewController alloc] initWithNibName:@&quot;AddTaskViewController&quot; bundle:[NSBundle mainBundle]];
    viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    
    // Nous indiquons que la classe appelante est le delegate de la classe appelée
    viewController.delegate = self;
    
    [self presentModalViewController:viewController animated:YES];
    [viewController release];
}

// Implémentation de la méthode du protocol, qui sera appelée
// lorsque l&#039;utilisateur ajoutera une tâche
- (void)taskDidAdd:(NSString *)name
{
    // On récupère la tâche ajoutée
    // et on peut l&#039;insérer dans le UITableView
}</pre>
<h4>Lien avec le Design Pattern Observateur</h4>
<p>On peut remarquer la similitude de ce Design Pattern avec le <a title="Design Pattern Observateur" href="http://fr.wikipedia.org/wiki/Observateur_(patron_de_conception)" target="_blank">Design Pattern Observateur</a>, qui permet d&rsquo;<strong>avertir une vue</strong> lorsque son modèle, auquel elle est <em>abonné</em>, se <strong>met à jour</strong>.</p>
<h4>Conclusion</h4>
<p>Ce Design Pattern est très utilisé dans le SDK iOS, on peut notamment le retrouver dans des objets tels que le <em>UITableView</em> ou le <em>UITextField</em>.</p>
<p>C&rsquo;est une bonne pratique à mettre en place dans vos projets afin d&rsquo;<strong>éviter de trop coupler vos objets</strong> et ainsi les rendre <strong>réutilisables</strong>, en effet vous noterez que je peux parfaitement réutiliser ma classe AddTaskViewController, puisqu&rsquo;elle n&rsquo;est <em>absolument pas liée</em> à la classe ListTaskViewController.</p>
<p><span style="color: #999999;"><em>* Les sources du projet sont disponibles <a href="http://www.evoluation.com/wp-content/uploads/2012/05/Task.zip">ici</a>.</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/05/protocol-delegate-un-puissant-design-pattern/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Comment utiliser le nouvel access token de Facebook avec Windows Phone</title>
		<link>http://www.evoluation.com/blog/2012/05/comment-utiliser-le-nouvel-access-token-de-facebook-avec-windows-phone/</link>
		<comments>http://www.evoluation.com/blog/2012/05/comment-utiliser-le-nouvel-access-token-de-facebook-avec-windows-phone/#comments</comments>
		<pubDate>Sat, 12 May 2012 15:34:56 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[access token]]></category>
		<category><![CDATA[exchange]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[fb_exchange_token]]></category>
		<category><![CDATA[windows phone]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=378</guid>
		<description><![CDATA[Depuis que Facebook implémente le protocole OAuth pour utiliser ses API, les développeurs doivent récupérer ce que l&#8217;on appelle un access token lors de la connexion pour pouvoir faire appel au Graph API. Un problème se pose alors : quelle est la durée de vie de cet access token et comment la gérer ? L&#8217;existant La méthode [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Depuis que Facebook implémente le <a title="Article Wikipédia sur OAuth" href="http://fr.wikipedia.org/wiki/OAuth" target="_blank">protocole OAuth</a> pour utiliser ses API, les développeurs doivent récupérer ce que l&rsquo;on appelle un <strong>access token</strong> lors de la connexion pour pouvoir faire appel au <a title="Graph API de Facebook" href="http://developers.facebook.com/docs/reference/api/" target="_blank">Graph API</a>. Un problème se pose alors : <em>quelle est la durée de vie de cet access token et comment la gérer ?</em></p>
<h4>L&rsquo;existant</h4>
<p>La méthode la plus courante pour gérer ce problème était jusqu&rsquo;à il y a peu de régler les paramètres de l&rsquo;application Facebook en activant le champ <strong>offline_access</strong>, ce qui avait pour effet de renvoyer un access token <strong>illimité</strong> dans le temps.</p>
<p>Or <a title="Article sur la suppression du offline_access de Facebook" href="http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/" target="_blank">cette option sera <strong>supprimée le 5 Juillet prochain</strong></a> et est d&rsquo;ores et déjà dépréciée, Facebook a donc mis en place une nouvelle méthode.</p>
<h4>Exchange access token</h4>
<p>La première chose à savoir est que lors de la connexion classique, un access token est toujours retourné, mais il n&rsquo;est désormais <strong>valide qu&rsquo;une à deux heures</strong>.</p>
<p>Il est donc nécessaire de faire appel à la nouvelle méthode mise en place par Facebook, qui se nomme <strong>exchange_access_token</strong>. Elle prend en paramètre l&rsquo;access token courant et en retourne un nouveau, qui a une <strong>durée de vie de 60 jours</strong>.</p>
<p>A noter que cette méthode renvoie <strong>un seul nouvel access token par jour</strong>, si vous appelez plusieurs fois cette méthode le même jour, le nouvel access token sera retourné <em>uniquement la première fois</em>. Ensuite ce sera le <em>même access token</em> qui sera retourné.</p>
<h4>Utilisation</h4>
<p>Afin de gérer au mieux toutes les situations possibles, il est conseillé d&rsquo;appeler cette méthode d&rsquo;échange d&rsquo;access token <em>aussi souvent que possible</em>. Cependant en sachant qu&rsquo;elle ne retourne qu&rsquo;un seul nouvel access token par jour, il n&rsquo;est pas utile de l&rsquo;appeler avant chaque requête (même si c&rsquo;est tout à fait possible), car cela ajoute une requête supplémentaire à chaque fois, et donc un temps de chargement légèrement plus long.</p>
<p>Le conseil que je donne est de n&rsquo;appeler cette méthode qu&rsquo;<strong>une seule fois par jour</strong> en enregistrant une valeur dans l&rsquo;Isolated Storage ou en base de données, qui indique si la méthode a déjà été appelé aujourd&rsquo;hui ou non.</p>
<h4>Mise en place</h4>
<p>Voici un exemple de code C# expliquant l&rsquo;appel à cette méthode dans une application Windows Phone. J&rsquo;utilise la bibliothèque externe <strong>Facebook C# SDK</strong>, qui peut facilement être installé à l&rsquo;<a title="L’installateur de bibliothèque .Net pour Visual Studio : Nuget" href="http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/">aide de l&rsquo;installateur de package Nuget</a> dont j&rsquo;ai parlé dans un précédent article. Si vous voulez en savoir plus sur l&rsquo;utilisation de cette bibliothèque, je vous recommande ce <a title="Accéder à Facebook avec Windows Phone" href="http://www.siteduzero.com/tutoriel-3-630488-acceder-a-facebook.html" target="_blank">tutoriel sur le Site du Zéro</a>.</p>
<pre class="wp-code-highlight prettyprint linenums:1">private void exchangeToken()
{
    FacebookClient client = new FacebookClient();

    // Affectation de l&#039;access token existant
    client.AccessToken = oldAccessToken; 

    client.GetCompleted += facebookClient_GetCompleted; 

    // Préparation de la requête d&#039;échange d&#039;access token
    Dictionary parameters = new Dictionary();
    parameters[&quot;client_id&quot;] = &quot;votre_client_id&quot;;
    parameters[&quot;client_secret&quot;] = &quot;votre_client_secret&quot;;
    parameters[&quot;grant_type&quot;] = &quot;fb_exchange_token&quot;;
    parameters[&quot;fb_exchange_token&quot;] = client.AccessToken; 

    client.GetAsync(&quot;https://graph.facebook.com/oauth/access_token&quot;, parameters, &quot;exchange_token&quot;);
}

private void facebookClient_GetCompleted(object sender, FacebookApiEventArgs e)
{
    if (e.Error == null)
    {
        if ((string)e.UserState == &quot;exchange_token&quot;)
        {
            JsonObject data = (JsonObject)e.GetResultData(); 

            // Enregistrement du nouvel access token
            string newAccessToken = (string)data[&quot;access_token&quot;]; 

            Dispatcher.BeginInvoke(() =&gt;
                MessageBox.Show(&quot;Votre compte Facebook a bien été configuré.&quot;, &quot;Félicitations !&quot;, MessageBoxButton.OK)
            );
        }
    }
    else
    {
        Dispatcher.BeginInvoke(() =&gt;
            MessageBox.Show(&quot;Erreur dans la configuration de votre compte Facebook.&quot;, &quot;Attention !&quot;, MessageBoxButton.OK)
        );
    }
}</pre>
<h4>Conclusion</h4>
<p>Ce nouveau fonctionnement permet donc de déconnecter l&rsquo;utilisateur de Facebook uniquement si cela fait <em>plus de deux mois</em> qu&rsquo;il n&rsquo;a pas utilisé l&rsquo;application Windows Phone (sauf <a title="Gérer les exceptions de l'expiration de l'access token Facebook" href="http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/" target="_blank">exceptions</a>), ce qui est finalement assez logique.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/05/comment-utiliser-le-nouvel-access-token-de-facebook-avec-windows-phone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Intégrer facilement l&#8217;effet Tilt dans son application Windows Phone</title>
		<link>http://www.evoluation.com/blog/2012/05/integrer-facilement-leffet-tilt-dans-son-application-windows-phone/</link>
		<comments>http://www.evoluation.com/blog/2012/05/integrer-facilement-leffet-tilt-dans-son-application-windows-phone/#comments</comments>
		<pubDate>Sat, 12 May 2012 14:22:18 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[effect]]></category>
		<category><![CDATA[silverlight toolkit]]></category>
		<category><![CDATA[tilt]]></category>
		<category><![CDATA[windows phone]]></category>
		<category><![CDATA[xaml]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=320</guid>
		<description><![CDATA[Une des particularités du développement pour Windows Phone est l&#8217;interface Métro : sa police, ses couleurs et ses animations. On retrouve notamment un effet au clic sur un élément d&#8217;une liste, où l&#8217;on a l&#8217;impression que l&#8217;élément s&#8217;enfonce un peu, c&#8217;est-ce que l&#8217;on appelle le Tilt Effect. De base, cet effet n&#8217;est pas disponible dans [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Une des particularités du développement pour Windows Phone est l&rsquo;<em>interface Métro</em> : sa police, ses couleurs et ses animations. On retrouve notamment un <em>effet au clic sur un élément d&rsquo;une liste</em>, où l&rsquo;on a l&rsquo;impression que l&rsquo;élément s&rsquo;enfonce un peu, c&rsquo;est-ce que l&rsquo;on appelle le <strong>Tilt Effect</strong>.</p>
<p>De base, cet effet n&rsquo;est <strong>pas disponible</strong> dans le SDK Windows Phone 7.1, cependant Microsoft a créé une <strong>bibliothèque externe</strong> permettant de l&rsquo;utiliser facilement.</p>
<h4>Installation du Silverlight toolkit pour Windows Phone</h4>
<p>La première étape est donc d&rsquo;installer la bibliothèque externe permettant de mettre en œuvre cet effet, elle s&rsquo;appelle <strong>Silverlight for Windows Phone Toolkit</strong>. Pour l&rsquo;installer je vous redirige vers mon précédent article portant sur l&rsquo;<a title="L’installateur de bibliothèque .Net pour Visual Studio : Nuget" href="http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/">installation de bibliothèque externe grâce à Nuget</a>.</p>
<h4>Utilisation de l&rsquo;effet</h4>
<p>Une fois la bibliothèque installée, l&rsquo;effet peut s&rsquo;utiliser soit en <strong>XAML</strong> soit en <strong>code behind</strong> (C# ou VB .Net). Le plus simple est d&rsquo;utiliser le XAML, pour cela il faut ajouter la <em>référence du namespace</em> suivante en haut de chaque fichier .xaml où l&rsquo;on utilisera l&rsquo;effet :</p>
<pre class="wp-code-highlight prettyprint linenums:1">xmlns:toolkit=&quot;clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit&quot;</pre>
<p>Il suffit ensuite d&rsquo;indiquer les contrôles sur lesquels nous voulons utiliser l&rsquo;effet :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;ListBox ItemsSource=&quot;{Binding Items}&quot; toolkit:TiltEffect.IsTiltEnabled=&quot;True&quot;&gt;
    &lt;ListBox.ItemTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;StackPanel&gt;
                &lt;TextBlock Text=&quot;{Binding LineOne}&quot; TextWrapping=&quot;Wrap&quot; /&gt;
                &lt;TextBlock Text=&quot;{Binding LineTwo}&quot; TextWrapping=&quot;Wrap&quot; /&gt;
            &lt;/StackPanel&gt;
        &lt;/DataTemplate&gt;
    &lt;/ListBox.ItemTemplate&gt;
&lt;/ListBox&gt;</pre>
<p>Ou encore :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;Button Text=&quot;Hello, world!&quot; toolkit:TiltEffect.IsTiltEnabled=&quot;True&quot; /&gt;</pre>
<p>Il est même possible de l&rsquo;utiliser sur tous les contrôles de la page à la fois :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;phone:PhoneApplicationPage
    // ...
    xmlns:toolkit=&quot;clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit&quot;
    // ...
    toolkit:TiltEffect.IsTiltEnabled=&quot;True&quot;&gt;</pre>
<p>A noter qu&rsquo;une option permettant de <strong>supprimer l&rsquo;effet Tilt sur un contrôle</strong> est aussi disponible. Cela est utile dans le cas où nous affectons l&rsquo;effet à toute la page et où nous ne voulons pas que tous les éléments en bénéficient. Ou encore dans le cas d&rsquo;une ListBox qui contient une Image et un TextBlock par exemple, et où nous voulons seulement affecter l&rsquo;effet au clic sur le TextBlock :</p>
<pre class="wp-code-highlight prettyprint linenums:1">&lt;ListBox ItemsSource=&quot;{Binding Items}&quot; toolkit:TiltEffect.IsTiltEnabled=&quot;True&quot;&gt;
    &lt;ListBox.ItemTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;StackPanel&gt;
                &lt;Image Source=&quot;{Binding Image}&quot; toolkit:TiltEffect.SuppressTilt=&quot;True&quot; /&gt;
                &lt;TextBlock Text=&quot;{Binding LineTwo}&quot; TextWrapping=&quot;Wrap&quot; /&gt;
            &lt;/StackPanel&gt;
        &lt;/DataTemplate&gt;
    &lt;/ListBox.ItemTemplate&gt;
&lt;/ListBox&gt;</pre>
<h4>Animer tous les contrôles</h4>
<p>Par défaut, seuls les contrôles <em>Button</em> et <em>ListBox</em> peuvent bénéficier de cet effet. Pour affecter l&rsquo;effet aux autres contrôles, comme la <em>CheckBox</em> ou le <em>RadioButton</em> par exemple, il faut les <strong>autoriser dans le code behind</strong> de cette manière :</p>
<pre class="wp-code-highlight prettyprint linenums:1">public MainPage()
{
    InitializeComponent();

    TiltEffect.TiltableItems.Add(typeof(RadioButton));
}</pre>
<h4>Et après ?</h4>
<p>La bibliothèque de Microsoft <em>Silverlight for Windows Phone Toolkit</em> apporte bien d&rsquo;autres possibilités, telles que les <strong>animations</strong> ou les <strong>transitions entre les pages</strong>. Et leur utilisation est aussi simple que pour l&rsquo;effet Tilt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/05/integrer-facilement-leffet-tilt-dans-son-application-windows-phone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>L&#8217;installateur de bibliothèque .Net pour Visual Studio : Nuget</title>
		<link>http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/</link>
		<comments>http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/#comments</comments>
		<pubDate>Tue, 01 May 2012 06:28:05 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[bibliothèque]]></category>
		<category><![CDATA[gratuit]]></category>
		<category><![CDATA[nuget]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[recherche]]></category>
		<category><![CDATA[silverlight toolkit]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[windows phone]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=294</guid>
		<description><![CDATA[Pour développer une application en .Net, il est de plus en plus utile et pratique d&#8217;utiliser des bibliothèques externes. Or l&#8217;installation de celles-ci n&#8217;est pas toujours une chose aisée, certaines bibliothèques peuvent dépendre d&#8217;autres bibliothèques pour fonctionner, il faut alors toutes les installer manuellement, tout comme les différentes mises à jour. C&#8217;est là où intervient [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Pour développer une application en .Net, il est de plus en plus utile et pratique d&rsquo;utiliser des bibliothèques externes. Or l&rsquo;installation de celles-ci n&rsquo;est pas toujours une chose aisée, certaines bibliothèques peuvent dépendre d&rsquo;autres bibliothèques pour fonctionner, il faut alors toutes les installer manuellement, tout comme les différentes mises à jour. C&rsquo;est là où intervient Nuget, un <strong>installateur de bibliothèque gratuit intégré à Visual Studio</strong>.</p>
<h4>Installation</h4>
<p>Le plugin Nuget est disponible à cette adresse : <a title="Téléchargement de Nuget" href="http://nuget.codeplex.com/" target="_blank">http://nuget.codeplex.com/</a>. Il suffit d&rsquo;exécuter le fichier téléchargé pour que celui-ci s&rsquo;installe. Un redémarrage de Visual Studio est ensuite nécessaire.</p>
<h4>Utilisation</h4>
<p>Une fois Nuget installé, il faut<strong> créer un nouveau projet</strong> ou <strong>ouvrir un projet existant</strong> pour en profiter. Un nouveau menu contextuel est alors disponible au clic droit sur la solution.</p>
<p style="text-align: center;"><a href="http://www.evoluation.com/wp-content/uploads/2012/05/menu-nuget.png" target="_blank"><img class="aligncenter size-full wp-image-296" title="Accès au menu contextuel Nuget au clic droit sur la solution" src="http://www.evoluation.com/wp-content/uploads/2012/05/menu-nuget.png" alt="" width="565" height="466" /></a></p>
<p>Au clic sur  <em>&laquo;&nbsp;Manage Nuget Packages&nbsp;&raquo;</em>, le plugin s&rsquo;ouvre dans une popup, faisant apparaître les bibliothèques les plus téléchargées. Un <strong>moteur de recherche</strong> est également disponible, faisons un test en recherchant le <em>Silverlight for Windows Phone Toolkit</em>.</p>
<p style="text-align: center;"><a href="http://www.evoluation.com/wp-content/uploads/2012/05/window-nuget.png" target="_blank"><img class="aligncenter  wp-image-299" title="Installation d'un package externe avec Nuget" src="http://www.evoluation.com/wp-content/uploads/2012/05/window-nuget.png" alt="" width="640" height="427" /></a></p>
<p>Il suffit ensuite de cliquer sur &laquo;&nbsp;<strong>Install</strong>&nbsp;&raquo; pour que la bibliothèque s&rsquo;installe automatiquement dans la solution, en ajoutant les références nécessaires. Dans la partie gauche, le menu &laquo;&nbsp;<strong>Updates</strong>&nbsp;&raquo; permet de mettre à jour automatiquement les différentes bibliothèques installés.</p>
<p>Grâce à Nuget, vous pouvez dorénavant installer vos bibliothèques .Net très rapidement et très simplement, directement à partir de Visual Studio.</p>
<p>Si vous voulez aller plus loin, une documentation du projet est disponible à cette adresse : <a title="Document de Nuget" href="http://docs.nuget.org/">http://docs.nuget.org/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/05/linstallateur-de-bibliotheque-net-pour-visual-studio-nuget/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redéfinir le design d&#8217;un UINavigationBar</title>
		<link>http://www.evoluation.com/blog/2012/04/redefinir-le-design-dun-uinavigationbar/</link>
		<comments>http://www.evoluation.com/blog/2012/04/redefinir-le-design-dun-uinavigationbar/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 10:28:40 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[barre de navigation]]></category>
		<category><![CDATA[changer]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[fond]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[look]]></category>
		<category><![CDATA[navigation bar]]></category>
		<category><![CDATA[redéfinir]]></category>
		<category><![CDATA[uinavigationbar]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=202</guid>
		<description><![CDATA[Lorsque l’on développe une application iPhone ou iPad, bien souvent on veut pouvoir la mettre à notre image, et l’un des éléments que l’on cherche à modifier en premier est l&#8217;objet UINavigationBar. Avant, j’utilisais une manière peu sécurisée pour y arriver : je créais une catégorie sur l’objet UINavigationBar que je plaçais dans mon fichier [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Lorsque l’on développe une application iPhone ou iPad, bien souvent on veut pouvoir la mettre à notre image, et l’un des éléments que l’on cherche à modifier en premier est l&rsquo;objet <strong>UINavigationBar</strong>.</p>
<p>Avant, j’utilisais une manière peu sécurisée pour y arriver : je créais une catégorie sur l’objet UINavigationBar que je plaçais dans mon fichier AppDelegate afin qu’il soit pris en compte par tous les objets UINavigationBar de mon application. Ca fonctionnait bien dans le simulateur, mais pas toujours sur un iDevice.</p>
<pre class="wp-code-highlight prettyprint linenums:1">@implementation UINavigationBar (MyNavigationBar)

- (void)drawRect:(CGRect)rect {
    UIImage *myBackgroundImage = [UIImage imageNamed:@&quot;navBar.png&quot;];
    [myBackgroundImage drawInRect:rect];
}

@end</pre>
<h4>Les best-practices</h4>
<p>Récemment, je suis tombé sur une vidéo d’Apple réalisée à la WWDC 2011 intitulé <strong>Improving The Stability Of Your Apps</strong> (*), qui explique justement que le hack que j’utilisais est incorrect et qu’il existe deux manières justes de le faire.</p>
<h5>Hériter de l’objet UINavigationBar</h5>
<p>La première solution est de créer une classe héritant de l&rsquo;objet UINavigationBar en surchargeant la méthode <strong>drawRect</strong> :</p>
<pre class="wp-code-highlight prettyprint linenums:1">@implementation MyNavigationBar

- (void)drawRect:(CGRect)rect {
    UIImage *image = [UIImage imageNamed:@&quot;navBar.png&quot;];
    [image drawInRect:rect];
}

@end</pre>
<p>Puis dans le(s) fichier(s) .xib où vous voulez modifier l’apparence de la barre de navigation, sélectionnez l’objet graphique UINavigationBar en question et cliquez sur l’onglet <strong>Identity Inspector</strong> dans la colonne de droite. Sous l’onglet <strong>Customer Class</strong>, renseignez le champ <strong>Class</strong> par le nom de notre nouvelle classe, soit : <strong>MyNavigationBar</strong>.</p>
<p style="text-align: center;"><a href="http://www.evoluation.com/wp-content/uploads/2012/04/custom-navigation-bar-class-1.png" target="_blank"><img class="aligncenter  wp-image-274" title="Surcharge de l'objet UINavigationBar" src="http://www.evoluation.com/wp-content/uploads/2012/04/custom-navigation-bar-class-1-1024x685.png" alt="" width="640" height="429" /></a></p>
<p>L&rsquo;avantage de cette solution est qu&rsquo;elle fonctionne avec iOS 4.</p>
<h5>Utiliser la fonction d’iOS 5</h5>
<p>Avec l&rsquo;arrivée d&rsquo;iOS 5, Apple a finalement décidé d&rsquo;intégrer <strong>nativement</strong> la possibilité de customiser l&rsquo;objet UINavigationBar très simplement.</p>
<p>Cela se fait à l&rsquo;aide de la méthode <strong>setBackgroundImage:forBarMetrics</strong> de l&rsquo;objet UINavigationBar. Pour son fonctionnement, je vous renvoie à la <a title="Documentation Apple UINavigationBar" href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationBar_Class/Reference/UINavigationBar.html" target="_blank">documentation d&rsquo;Apple</a>, cela n&rsquo;étant pas le but de cet article.</p>
<h4>L’héritage d’un objet UINavigationBar en pratique</h4>
<p>L’héritage de l’objet UINavigationBar fonctionne bien et est très simple à mettre en oeuvre, surtout si vous ajoutez vous-même un objet graphique UINavigationBar dans votre fichier .xib.</p>
<p>Mais qu’en est-il lorsque vous voulez utiliser cette méthode avec un <strong>UISplitViewController</strong> par exemple ? Car dans ce cas-là la barre de navigation n’est pas visible graphiquement.</p>
<p>Il existe une petite astuce toute simple pour réussir à mettre en place ce système dans le fichier .xib. Il suffit simplement d’étirer la barre de gauche qui contient le <strong>File’s owner</strong>, le <strong>First Responder</strong> et vos différentes vues, afin de voir apparaître l’arborescence de vos objets graphiques.</p>
<p>Dépliez alors votre objet UISplitViewController autant de fois que possible pour finalement faire apparaître l’objet UINavigationBar à l’intérieur de celui-ci. Il suffit ensuite de modifier sa propriété <strong>Class</strong> dans la colonne <strong>Identity Inspector</strong> comme indiqué plus haut dans l’article.</p>
<p style="text-align: center;"><a href="http://www.evoluation.com/wp-content/uploads/2012/04/custom-navigation-bar-class-2.png" target="_blank"><img class="aligncenter  wp-image-277" title="Surcharge de l'objet UINavigationBar, non visible par défaut" src="http://www.evoluation.com/wp-content/uploads/2012/04/custom-navigation-bar-class-2-1024x603.png" alt="" width="640" height="377" /></a></p>
<p>Compilez, et admirez ! ;-)</p>
<p><span style="color: #999999;"><em>* Beaucoup de vidéos sont maintenant disponible à n’importe quel utilisateur ayant un compte Apple Developer, payant ou non.</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2012/04/redefinir-le-design-dun-uinavigationbar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pourquoi je veux un iPad</title>
		<link>http://www.evoluation.com/blog/2011/10/pourquoi-je-veux-un-ipad/</link>
		<comments>http://www.evoluation.com/blog/2011/10/pourquoi-je-veux-un-ipad/#comments</comments>
		<pubDate>Fri, 21 Oct 2011 11:23:56 +0000</pubDate>
		<dc:creator>Nicolas Bichon</dc:creator>
				<category><![CDATA[Réflexions]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[développeur informatique]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[marketing]]></category>
		<category><![CDATA[utilité]]></category>

		<guid isPermaLink="false">http://www.evoluation.com/?p=95</guid>
		<description><![CDATA[Apple a le don de créer des appareils qui donnent envie, l&#8217;iPad en est le dernier exemple. Donc moi aussi, j&#8217;en veux un&#8230; Mais pourquoi ? Un marketing nommé Apple Qui peut résister à un marketing aussi bien calibré que celui d&#8217;Apple (à part les anti-Apple) ? Tout est prévu pour nous faire craquer, du [...]]]></description>
				<content:encoded><![CDATA[<p class="lettrine">Apple a le don de créer des appareils qui <em>donnent envie</em>, l&rsquo;iPad en est le dernier exemple. Donc moi aussi, j&rsquo;en veux un&#8230; Mais pourquoi ?</p>
<h4>Un marketing nommé Apple</h4>
<p>Qui peut résister à un marketing aussi bien calibré que celui d&rsquo;Apple (à part les anti-Apple) ? Tout est prévu pour nous faire craquer, du design de l&rsquo;objet en lui-même, en passant par la boîte le contenant, sa médiatisation, sa publicité, <a href="http://www.apple.com/apple-events/" target="_blank">ses fameuses Keynotes</a>. Bref tout autour de l&rsquo;iPad est fait pour donner <em>envie</em> de l&rsquo;acheter. Seulement parfois, ça ne suffit pas.</p>
<h4>L&rsquo;iPad : pour qui ?</h4>
<p>A première vue, je dirais que le public de l&rsquo;iPad sont les personnes agées, les personnes n&rsquo;étant pas habituées à un ordinateur et tous ceux qui n&rsquo;ont pas encore d&rsquo;ordinateurs chez eux. Pour toutes ces personnes, l&rsquo;achat d&rsquo;un iPad me semble justifié :</p>
<ul>
<li><strong>Facilité d&rsquo;utilisation</strong> de l&rsquo;appareil, même pour un novice,</li>
<li><strong>Prix moindre</strong> pour faire le stricte nécessaire sur un ordinateur (photos, vidéos, Web, Email). Il y a les netbooks qui sont moins chers pour plus de fonctionnalités, mais soyons francs, un netbook c&rsquo;est nul.</li>
</ul>
<p>Or je suis Ingénieur Informatique. Besoin d&rsquo;un ordinateur ? J&rsquo;en ai déjà un évidemment. Besoin d&rsquo;un Smartphone éventuellement pour consulter ses mails, jouer à Fruits Ninja ? J&rsquo;en ai un aussi. Quelle est donc la place pour un iPad chez moi ? Entre le Smartphone et l&rsquo;ordinateur, comme Steve Jobs l&rsquo;avait présenté lors de sa Keynote ? Non.</p>
<p>En fait pour un développeur informatique, la réponse est simple : l&rsquo;iPad ne sert à <strong>rien</strong> ! Oui ça frustre, oui j&rsquo;ai longtemps chercher une excuse pour m&rsquo;en acheter un, mais rien à faire. Je n&rsquo;en ai juste <em>aucune utilité</em>.</p>
<h4>Ah si, j&rsquo;ai trouvé une raison !</h4>
<p>La seule et selon moi, bonne raison de m&rsquo;acheter un iPad, est que je suis justement développeur pour iPhone / iPad. J&rsquo;ai donc trouvé une bonne raison : <em>mon métier</em> !</p>
<p>En fait, je me suis déjà acheté un iPad 2&#8230; Alors mon point de vue a-t-il changé sur son utilité après m&rsquo;en être servi au quotidien ?</p>
<h4>Ceci est une révolution</h4>
<p>La première et la plus importante des utilités pour moi est le <strong>test d&rsquo;applications</strong> que j&rsquo;ai développé <strong>sur un matériel réel</strong>.</p>
<p>La seconde tout aussi importante, est de <strong>pouvoir installer et essayer plusieurs applications de l&rsquo;AppStore</strong> et ainsi voir ce qui existe sur le marché des application mobiles. De la veille technologique en quelque sorte.</p>
<p>Soit. Ces deux premières utilisations coulent de source par rapport à mon métier. Mais à part çà, quel est l&rsquo;apport d&rsquo;un iPad par rapport à un ordinateur ou à un Smartphone ?</p>
<p>Et bien je verrais deux principales utilités :</p>
<ul>
<li>1/ J&rsquo;ai enfin assouvi mon envie, j&rsquo;ai fait mon bon consommateur et je me suis acheté cet objet tant désiré ! Ca fait du bien&#8230;</li>
<li>2/ Celle-là est juste énorme : je peux lire mes news, avec mes doigts, vautrés dans mon lit ou mon canapé, sur le ventre ou sur le dos&#8230;</li>
</ul>
<p>Ils sont forts chez Apple.</p>
<h4>Le mot de la fin</h4>
<p>Plus sérieusement, l&rsquo;apport réel de l&rsquo;iPad est l&rsquo;<strong>expérience utilisateur</strong> qu&rsquo;il procure. Que ce soit pour parcourir le Web (&laquo;&nbsp;The whole Internet is in your hands&nbsp;&raquo; comme Steve Jobs le disait si bien) ou utiliser des applications natives. Et c&rsquo;est bien là qu&rsquo;est la vrai force de l&rsquo;iPad selon moi.</p>
<p>C&rsquo;est aussi là que mon métier est excitant : développer des applications en tentant d&rsquo;apporter une expérience utilisateur riche.</p>
<p>Et vous, si vous voulez un iPad ou si vous en avez déjà un, pourquoi ?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evoluation.com/blog/2011/10/pourquoi-je-veux-un-ipad/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
