<?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>netinfluence&#039;s blog &#187; macmade</title>
	<atom:link href="http://blog.netinfluence.com/author/macmade/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.netinfluence.com</link>
	<description>le blog de l&#039;agence netinfluence</description>
	<lastBuildDate>Fri, 13 Jan 2012 10:39:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>XCode: librairies statiques et catégories</title>
		<link>http://blog.netinfluence.com/2010/06/23/xcode-librairies-statiques-et-categories/</link>
		<comments>http://blog.netinfluence.com/2010/06/23/xcode-librairies-statiques-et-categories/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 14:56:36 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[conseils]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=1926</guid>
		<description><![CDATA[Il est souvent pratique de scinder un projet XCode en plusieurs parties distinctes: le code permettant de contrôler les différents éléments de l'interface, et le code indépendant de l'interface (outils, librairies, etc).
Une telle découpe présente de nombreux avantage, notamment un meilleur contrôle des options de compilation pour chaque partie ainsi q'un temps de compilation réduit, puisque chaque partie est compilée séparément, et uniquement en cas de besoin.
Cet article explique comment paramétrer un projet XCode pour une telle utilisation.]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small"> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a href="http://www.gnu.org/copyleft/fdl.html" title="Free Documentation License">http://www.gnu.org/copyleft/fdl.html</a></div>
</div>
<div>
Il est souvent pratique de scinder un projet XCode en plusieurs parties distinctes: le code permettant de contrôler les différents éléments de l&#8217;interface, et le code indépendant de l&#8217;interface (outils, librairies, etc).<br />
Une telle découpe présente de nombreux avantage, notamment un meilleur contrôle des options de compilation pour chaque partie ainsi q&#8217;un temps de compilation réduit, puisque chaque partie est compilée séparément, et uniquement en cas de besoin.<br />
Cet article explique comment paramétrer un projet XCode pour une telle utilisation.
</div>
<h2>Création d&#8217;un projet</h2>
<div>
Nous allons tout d&#8217;abord créer un nouveau projet XCode pour iPhone (la procédure est exactement similaire dans le cas d&#8217;une application Mac OS X).
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-1.png" />
</div>
<div>
XCode crée par défaut les fichiers nécessaires au fonctionnement d&#8217;une application basique.
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-2.png" />
</div>
<div>
La section «Targets» comprend les différents éléments pouvant être produits par notre projet XCode.
</div>
<div>
Dans ce cas là, il s&#8217;agit d&#8217;une application. Ce type de cible est composée de la copie des resources (les fichiers XIB &#8211; interface utilisateur), de la compilation du code source de l&#8217;application, et finalement de la liaison (lainage) du code objet généré avec les librairies et frameworks utilisés par l&#8217;application.
</div>
<div>
Il est possible de définir pour une cible des paramètres de compilation spécifiques, via le menu contextuel,
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-3.png" />
</div>
<h2>Cibles</h2>
<div>
Un projet XCode peut être composé de plusieurs cibles. Cela est nécessaire si l&#8217;on intègre des librairies externes, mais cela peut également être pratique pour séparer un projet et ainsi optimiser la compilation de l&#8217;application finale.
</div>
<div>
Nous allons commencer par créer une nouvelle classe, que nous allons nommer «MethodProvider», dont le but est, comme son nom l&#8217;indique, de mettre à disposition des méthode génériques pour notre application.
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-4.png" />
</div>
<div>
Nous allons y intégrer une méthode statique nommée doSomething.
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-comment">/* MethodProvider.h */</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">&lt;UIKit/UIKit.h&gt;</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> MethodProvider: NSObject</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">+ ( <span class="macmade-code-keyword">void</span> )doSomething;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-comment">/* MethodProvider.m */</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MethodProvider.h"</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> MethodProvider</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">+ ( <span class="macmade-code-keyword">void</span> )doSomething</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"Method 'doSomething' called..."</span> );</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Nous allons également appeler cette méthode depuis notre application, lorsque celle-ci aura terminé son chargement. Cela se passe dans la méthode «application:didFinishLaunchingWithOptions:»  de la classe «MyAppAppDelegate»:
</div>
<div class="macmade-code">
<code class="macmade-source">- ( <span class="macmade-code-keyword">BOOL</span> )application: ( <span class="macmade-code-predefined">UIApplication</span> * )application didFinishLaunchingWithOptions: ( <span class="macmade-code-predefined">NSDictionary</span> * )launchOptions</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">window</span> <span class="macmade-code-predefined">addSubview</span>: <span class="macmade-code-ctag">viewController</span>.<span class="macmade-code-predefined">view</span> ];</code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">window</span> makeKeyAndVisible ];</code><br />
<code class="macmade-source">    </code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">MethodProvider</span> doSomething ];</code><br />
<code class="macmade-source">    </code><br />
<code class="macmade-source">    <span class="macmade-code-keyword">return YES</span>;</code><br />
<code class="macmade-source">}</code>
</div>
<div>
Ne pas oublier d&#8217;include le fichier .h de la classe «MethodProvider» dans le fichier «MyAppAppController.m»:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MyAppAppDelegate.h"</span></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MyAppViewController.h"</span></code><br />
<code class="macmade-source"><strong><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MethodProvider.h"</span></strong></code>
</div>
<div>
Dans ce cas là, la classe «MethodProvider» est compilée avec les autres fichiers sources de notre application. Nous allons maintenant faire en sorte qu&#8217;elle le soit séparément.
</div>
<div>
En premier lieu, nous allons ôter cette classe de la cible de notre application. Cela peut être effectué en décochant la case à côté du fichier source.
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-5.png" />
</div>
<div>
A partir de ce moment là, la classe ne sera plus compilée en même temps que l&#8217;application. La compilation de l&#8217;application va donc échouer avec le message suivant:
</div>
<div>
<pre>
_OBJC_CLASS_$_MethodProvider", referenced from:
objc-class-ref-to-MethodProvider in MyAppAppDelegate.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
</pre>
</div>
<div>
Ce message veut tout simplement dire que le linker n&#8217;a pas réussi à trouver le symbole correspondant à notre classe, alors qu&#8217;il est utilisé depuis la classe MyAppAppDelegate.
</div>
<div>
Nous allons donc créer une nouvelle cible, qui aura pour but de compiler la classe «MethodProvider».
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-6.png" />
</div>
<h2>Librairie statique</h2>
<div>
Cette cible sera de type «static library»:
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-7.png" />
</div>
<div>
Une librairie est un format spécifique de code object (compilé), dont le but est de fournir des fonctions aux applications désirant les utiliser. Une librairie peut être de deux types: statique ou dynamique.
</div>
<div>
Dans le cas d&#8217;une librairie statique, le code objet de la librairie est intégré au binaire de l&#8217;application lors de la compilation.<br />
Il en résulte un seul fichier binaire, contenant à la fois le code de l&#8217;application et le code de la librairie. Le binaire est donc plus lourd, mais la libraire n&#8217;a pas besoin d&#8217;être présente sur la machine hôte.
</div>
<div>
Dans le cas d&#8217;une librairie dynamique, seul son adresse est inclue dans le code de l&#8217;application, et c&#8217;est le kernel (via un linker) qui chargera le code de la libraire en mémoire à chaque fois que l&#8217;application est lancée. Le binaire est dans ce cas plus léger, mais la librairie doit impérativement être présente sur la machine hôte. Le temps de lancement de l&#8217;application peut en outre être un peu plus long. Le principal avantage d&#8217;une librairie dynamique est que plusieurs applications peuvent reposer sur la même librairie.
</div>
<div>
Dans notre cas, c&#8217;est donc bien sûr une libraire statique qu&#8217;il nous faut. Qui plus est, sur iOS, il est actuellement impossible de générer une libraire dynamique.
</div>
<div>
Lorsque plusieurs cibles sont disponibles, XCode permet de passer de l&#8217;une à l&#8217;autre via un menu déroulant, se trouvant dans la barre d&#8217;outils:
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-8.png" />
</div>
<div>
Nous pouvons donc passer sur notre cible «Methods», et y ajouter le(s) fichiers devant être compilés:
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-9.png" />
</div>
<div>
Nous pouvons également voir, au passage, notre librairie dans la section «Products»:
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-10.png" />
</div>
<div>
Il nous reste à lier notre application principale avec cette librairie. Cela est effectué depuis la phase «Link Binary With Libraries» de la cible de l&#8217;application.
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-11.png" />
</div>
<div>
Nous pouvons maintenant y ajouter notre librairie.
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-12.png" />
</div>
<div>
La dernière étape consiste à indiquer à XCode que notre application dépend de la librairie, pour que cette dernière soit compilée avant l&#8217;application, en cas de besoin. Cette opération est effectuée en ajoutant une dépendance, dans la section «General», dans les informations de la cible de l&#8217;application:
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-13.png" />
</div>
<div>
Nous pouvons maintenant compiler notre application sans problème.
</div>
<div>
Cette procédure peut être utilisée, comme dans cet exemple, pour séparer différentes parties de notre code.<br />
C&#8217;est également la procédure à utiliser lors de l&#8217;utilisation de sources et librairies externes, comme par exemple OpenCV (C++), JSON-Framework (Obj-C), etc.<br />
Il est bien sûr possible d&#8217;inclure les fichiers sources dans la même cible que l&#8217;application, mais un tel scénario nous prive de la possibilité de spécifier des paramètres de compilation spécifiques et risque de rallonger inutilement le temps de compilation de la cible principale.
</div>
<h2>Catégories</h2>
<div>
Il faut encore noter que, dans le cas de l&#8217;utilisation de catégories, l&#8217;utilisation d&#8217;une librairie statique peut se révéler problématique.<br />
Pour rappel, en Objective-C, une catégorie permet d&#8217;ajouter des méthodes dans une classe existante.
</div>
<div>
Ajoutons donc une catégorie sur UIApplication, dans la cible de notre librairie:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-comment">/* MyUIApp.h */</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">&lt;UIKit/UIKit.h&gt;</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> UIApplication( MyUIApp )</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )sayHello;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-comment">/* MyUIApp.m */</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MyUIApp.h"</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> UIApplication( MyUIApp )</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )sayHello</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"Hello"</span> );</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Et utilisons cette méthode dans notre application:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-comment">/* MyAppAppDelegate.m */</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">BOOL</span> )application: ( <span class="macmade-code-predefined">UIApplication</span> * )application didFinishLaunchingWithOptions: ( <span class="macmade-code-predefined">NSDictionary</span> * )launchOptions</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">window</span> <span class="macmade-code-predefined">addSubview</span>: <span class="macmade-code-ctag">viewController</span>.<span class="macmade-code-predefined">view</span> ];</code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">window</span> makeKeyAndVisible ];</code><br />
<code class="macmade-source">    </code><br />
<code class="macmade-source">    [ <span class="macmade-code-ctag">MethodProvider</span> doSomething ];</code><br />
<code class="macmade-source">    [ application sayHello ];</code><br />
<code class="macmade-source">    </code><br />
<code class="macmade-source">    <span class="macmade-code-keyword">return YES</span>;</code><br />
<code class="macmade-source">}</code>
</div>
<div>
Sans oublier d&#8217;inclure le fichier header:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">"MyUIApp.h"</span></code>
</div>
<div>
La compilation se déroulera sans aucun problème, mais l&#8217;application plantera, avec le message suivant (affiché dans la console):
</div>
<div>
<pre>
- [ UIApplication sayHello ]: unrecognized selector sent to instance 0x5911700
</pre>
</div>
<div>
Ce cas particulier est dû au côté dynamique d&#8217;Objective-C (la résolution des méthodes est faite par la couche run-time), est au spécificités du linker, qui ne génère par défaut pas de symboles pour les catégories.
</div>
<div>
Pour régler ce problème, il suffit de modifier les paramètres du linker, dans les informations de la cible de l&#8217;application, et y ajouter, dans la section «Other Linker Flags»:
</div>
<div>
<pre>
-ObjC -all_load
</pre>
</div>
<div>
<img src="/wp-content/uploads/macmade/objc-lib-14.png" />
</div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2010/06/23/xcode-librairies-statiques-et-categories/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Méthodes privées en Objective-C</title>
		<link>http://blog.netinfluence.com/2010/03/04/methodes-privees-en-objective-c/</link>
		<comments>http://blog.netinfluence.com/2010/03/04/methodes-privees-en-objective-c/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 12:44:02 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=1295</guid>
		<description><![CDATA[En Objective-C, contrairement à de nombreux autres langages orientés objet, le concept de méthode privée n'existe pas en tant que tel. Ce concept peut par contre être implémenté de plusieurs façons. Cet article présente 3 solutions possibles, avec leurs avantages et inconvénients.]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small"> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a href="http://www.gnu.org/copyleft/fdl.html" title="Free Documentation License">http://www.gnu.org/copyleft/fdl.html</a></div>
</div>
<h2>Introduction</h2>
<div>
En Objective-C, contrairement à de nombreux autres langages orientés objet, le concept de méthode privée n&#8217;existe pas en tant que tel.
</div>
<div>
Dans la déclaration de l&#8217;interface d&#8217;une classe, il est possible de définir une visibilité pour les variables d&#8217;instances.
</div>
<div>
Par exemple:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo: NSObject</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@public</span></code><br />
<code class="macmade-source">	</code><br />
<code class="macmade-source">	<span class="macmade-code-keyword">id</span> <span class="macmade-code-ctag">somePublicObject</span>;</code><br />
<code class="macmade-source">	</code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@protected</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">	<span class="macmade-code-keyword">id</span> <span class="macmade-code-ctag">someProtectedObject</span>;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@private</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">	<span class="macmade-code-keyword">id</span> <span class="macmade-code-ctag">somePrivateObject</span>;</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">+ ( <span class="macmade-code-keyword">void</span> )someStaticMethod;</code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )someMemberMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Les variables d&#8217;instances peuvent être regroupées en fonction de leur visibilité: publique (accessible depuis l&#8217;extérieur), protégée (accessible depuis la classe et les classes filles), et privée (accessible depuis la classe uniquement).
</div>
<div>
Il n&#8217;existe rien de tel pour les méthodes, au niveau de la déclaration de l&#8217;interface. Cependant, il est parfaitement possible d&#8217;implémenter le concept de méthodes privées, et ce de plusieurs façons.
</div>
<h2>Solution 1 &#8211; Implémentation</h2>
<div>
La première solution, et sans doute la plus évidente, consiste simplement à déclarer des méthodes dans l&#8217;implémentation.<br />
Dans un tel cas, ces méthodes ne seront pas visibles depuis l&#8217;extérieur, étant donné qu&#8217;elles ne sont pas présentes dans l&#8217;interface.
</div>
<div>
Par exemple:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo: NSObject</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePrivateMethod</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	[ <span class="macmade-code-keyword">self</span> <span class="macmade-code-ctag">somePrivateMethod</span> ];</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Le principal problème avec cette approche est que les méthodes &#8220;privées&#8221; doivent impérativement être déclarées avant le code y faisant référence, sous peine d&#8217;une erreur lors de la compilation.<br />
Dans l&#8217;exemple précédent, nous n&#8217;aurions pas pu déclarer &#8220;somePublicMethod&#8221; avant &#8220;somePrivateMethod&#8221;.<br />
Dans certains cas, lors d&#8217;appels cycliques par exemple, il est tout simplement impossible d&#8217;utiliser cette solution.
</div>
<h2>Solution 2 &#8211; Fonctions statiques</h2>
<div>
Une deuxième solution consiste à l&#8217;utilisation de fonctions statiques.<br />
En langage C, une fonction statique n&#8217;est visible que pour les fonctions se trouvant dans le même fichier.<br />
Il est à noter que, bien que l&#8217;on utilise également dans ce cas le mot clé &#8216;static&#8217;, celui-ci à un tout autre sens que si on l&#8217;utilise pour une variable, à l&#8217;intérieur d&#8217;une fonction.
</div>
<div>
Autrement dit:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">static void</span> somePrivateFunction( <span class="macmade-code-keyword">void</span> );</code><br />
<code class="macmade-source"><span class="macmade-code-keyword">static void</span> somePrivateFunction( <span class="macmade-code-keyword">void</span> )</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	<span class="macmade-code-ctag">somePrivateFunction</span>();</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Il s&#8217;agit d&#8217;une fonction, et non d&#8217;une méthode. Il est par contre possible, depuis cette fonction, d&#8217;accéder aux autres méthodes, et même aux variables d&#8217;instances.<br />
Pour réaliser cela, il suffit de passer l&#8217;instance en paramètre de la fonction:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">static void</span> somePrivateFunction( Foo * obj );</code><br />
<code class="macmade-source"><span class="macmade-code-keyword">static void</span> somePrivateFunction( Foo * obj )</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	/* Appel d'une méthode de la classe */</code><br />
<code class="macmade-source">	[ obj <span class="macmade-code-ctag">someOtherMethod</span> ];</code><br />
<code class="macmade-source">	</code><br />
<code class="macmade-source">	/* Accès à une variable d'instance de la classe */</code><br />
<code class="macmade-source">	obj-><span class="macmade-code-ctag">someInstanceVariable</span> = <span class="macmade-code-keyword">NULL</span>;</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	<span class="macmade-code-ctag">somePrivateFunction</span>( <span class="macmade-code-keyword">self</span> );</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Une instance d&#8217;une classe est tout simplement (ou presque) un pointeur vers une structure C. L&#8217;opérateur &#8216;->&#8217; peut donc parfaitement être utilisé pour accéder à une variable d&#8217;instance, qui n&#8217;est autre qu&#8217;un membre de cette structure.
</div>
<h2>Solution 3 &#8211; Catégories</h2>
<div>
Une dernière solution, sans doute la plus propre, consiste à utiliser des catégories. Ces dernières sont utilisées pour ajouter des méthodes dans une classe existante.
</div>
<div>
Par exemple:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo: NSObject</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo( private )</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePrivateMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> ) somePublicMethod</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	[ <span class="macmade-code-keyword">self</span> <span class="macmade-code-ctag">somePrivateMethod</span> ];</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo( private )</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> ) somePrivateMethod</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Ici, nous définissons l&#8217;interface de la classe Foo, ainsi qu&#8217;une catégorie nommée &#8220;private&#8221; (ce nom peut être n&#8217;importe lequel).<br />
Nous avons donc ensuite deux implémentations. Une pour les méthodes publiques, et l&#8217;autre pour les privées.<br />
Au niveau des headers, seule l&#8217;interface de base doit être présente, bien évidemment. La déclaration de la catégorie doit se faire dans le fichier contenant l&#8217;implémentation.
</div>
<div>
Il est à noter qu&#8217;il est également possible avec ce système d&#8217;utiliser une seule et unique implémentation. Pour ce faire, il suffit de déclarer une catégorie sans nom:
</div>
<div class="macmade-code">
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo: NSObject</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePublicMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@interface</span> Foo()</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )somePrivateMethod;</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> Foo</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> ) somePublicMethod</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source">	[ <span class="macmade-code-keyword">self</span> <span class="macmade-code-ctag">somePrivateMethod</span> ];</code><br />
<code class="macmade-source">}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> ) somePrivateMethod</code><br />
<code class="macmade-source">{}</code><br />
<code class="macmade-source"></code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@end</span></code>
</div>
<div>
Dès lors, puisque les méthodes privées sont définies dans la catégorie, leur ordre de déclaration dans l&#8217;implémentation n&#8217;a plus aucune importance, contrairement à la première solution présentée ici.
</div>
<h2>Quelle solution choisir?</h2>
<div>
Ces trois solutions fonctionnent très bien. Personnellement, j&#8217;ai tendance à éviter la première, principalement en raison de l&#8217;ordre de déclaration, et aussi parce que les méthodes privées sont difficilement repérables dans le code.<br />
L&#8217;utilisation de catégories permet au code de rester clair et lisible, l&#8217;implémentation des méthodes privées pouvant se faire dans un autre fichier que l&#8217;implémentation des méthodes publiques. Cela permet du coup d&#8217;identifier immédiatement la visibilité d&#8217;une méthode.
</div>
<div>
C&#8217;est donc cette troisième solution que je préconise, est qui certainement la plus adaptée au langage Objective-C.
</div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2010/03/04/methodes-privees-en-objective-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mac / iPhone / iPad – Détecter l’inactivité de l’utilisateur avec I/O Kit</title>
		<link>http://blog.netinfluence.com/2010/02/09/mac-iphone-ipad-detecter-linactivite-de-lutilisateur-avec-io-kit/</link>
		<comments>http://blog.netinfluence.com/2010/02/09/mac-iphone-ipad-detecter-linactivite-de-lutilisateur-avec-io-kit/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 16:26:43 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=855</guid>
		<description><![CDATA[Il peut être parfois utile, dans une application, de savoir si l'utilisateur est en train d'intéragir avec son ordinateur (ou téléphone) ou s'il est parti boire un café.
Cet article explique comment détecter l'inactivité de l'utilisateur. Il s'applique aussi bien au développement pour Mac OS X que pour iPhone / iPad.]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small">Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a title="Free Documentation License" href="http://www.gnu.org/copyleft/fdl.html">http://www.gnu.org/copyleft/fdl.html</a></div>
</div>
<div>Il peut être parfois utile, dans une application, de savoir si l&#8217;utilisateur est en train d&#8217;intéragir avec son ordinateur (ou téléphone) ou s&#8217;il est parti boire un café.<br />
Cet article explique comment détecter l&#8217;inactivité de l&#8217;utilisateur. Il s&#8217;applique aussi bien au développement pour Mac OS X que pour iPhone / iPad.</div>
<h3>I/O Kit</h3>
<div>Il n&#8217;existe à ma connaissance pas de moyen direct, en Cocoa, pour déterminer l&#8217;inactivité.<br />
Par inactivité, il faut comprendre absence d&#8217;interaction de l&#8217;utilisateur avec la machine. L&#8217;interaction peut être le déplacement de la souris, une action sur le clavier, etc, mais non une action déclenchée uniquement par la machine.</div>
<div>Le système dispose bien entendu de cette information. C&#8217;est ce qui permet de déclencher un économiseur d&#8217;écran, ou de mettre la machine en veille.</div>
<div>Pour accéder à cette information, nous allons devoir utiliser I/O Kit.<br />
Il s&#8217;agit d&#8217;une collection de frameworks, librairies et outils destinés principalement au développement de drivers pour des composants matériels.</div>
<div>Dans notre cas, nous allons utiliser plus principalement IOKitLib, une librairie permettant aux applications d&#8217;accéder aux ressources matérielles par le biais du kernel.</div>
<div>Comme il s&#8217;agit d&#8217;une librairie de (relativement) bas niveau, nous allons devoir coder en C pour l&#8217;utiliser.<br />
Nous allons donc, pour des raison pratiques, et pour permettre une utilisation générique, créer une classe Objective-C encapsulant ce code C parfois un peu moins digeste pour certains développeurs Cocoa et iPhone.</div>
<h3>Configuration du projet</h3>
<div>Avant de commencer, nous allons configurer notre projet XCode, afin de permettre l&#8217;utilisation de IOKitLib.<br />
En effet, puisqu&#8217;il s&#8217;agit d&#8217;une librairie, celle-ci doit être «linkée» à notre application finale.</div>
<div>Il suffit d&#8217;ajouter un framework à notre projet:</div>
<div><img src="/wp-content/uploads/macmade/framework-add.png" alt="" width="377" height="267" /></div>
<div>Pour une application Mac OS X, nous allons choisir &#8220;IOKit.framework&#8221;.<br />
Pour iPhone et iPad, ce framework n&#8217;est pas disponible dans son ensemble. Dans un tel cas, il faudra choisir &#8220;libIOKit.dylib&#8221;.</div>
<div><img src="/wp-content/uploads/macmade/framework-list.png" alt="" width="338" height="534" /></div>
<div>Le framework est du coup ajouté à notre projet, et sera «linké» avec notre application après la compilation.</div>
<div><img src="/wp-content/uploads/macmade/framework-cocoa.png" alt="" width="250" height="120" /><br />
<img src="/wp-content/uploads/macmade/framework-iphone.png" alt="" width="250" height="120" /></div>
<h3>Utilisation d&#8217;IOKitLib</h3>
<div>Avant toute chose, voici les documents de références d&#8217;I/O Kit:</div>
<ul>
<li> <a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/IOKit/IOKitLib_h/">IOKitLib</a></li>
<li> <a href="http://developer.apple.com/mac/library/documentation/DeviceDrivers/Conceptual/AccessingHardware/">Accessing Hardware</a></li>
<li> <a href="http://developer.apple.com/mac/library/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/">I/O Kit Fundamentals</a></li>
</ul>
<div>Nous allons tout d&#8217;abord créer une classe Objective-C qui nous permettra de connaître l&#8217;inactivité:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">#include</span> <span class="macmade-code-string">&lt;IOKit/IOKitLib.h&gt;</span></code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">@interface</span> IdleTime: NSObject</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">mach_port_t</span> <span class="macmade-code-ctag">ioPort</span>;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">io_iterator_t</span><span class="macmade-code-ctag"> ioIterator</span>;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">io_object_t</span> <span class="macmade-code-ctag">ioObject</span>;</code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">@property</span>( <span class="macmade-code-keyword">readonly</span> ) <span class="macmade-code-predefined">uint64_t</span> timeIdle;</code><br />
<code class="macmade-source"><span class="macmade-code-keyword">@property</span>( <span class="macmade-code-keyword">readonly</span> ) <span class="macmade-code-predefined">NSUInteger</span> secondsIdle;</code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>Cette classe contient 3 variables d&#8217;instances qui nous servirons à communiquer avec I/O Kit.<br />
Les types correspondants à ces variables sont définis dans le fichier &#8220;IOKit/IOKitLib.h&#8221;, que nous incluons.</div>
<div>Nous définissons également deux propriétés, qui nous servirons à accéder au temps inactif. La première en nanosecondes (ce que nous retournera I/O Kit), et la seconde en secondes (ce qui est souvent un peu plus pratique).</div>
<div>Voici l&#8217;implémentation basique de la classe:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">#include</span> <span class="macmade-code-string">"IdleTime.h"</span></code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> IdleTime</code></p>
<p><code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )init</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">if</span>( (<span class="macmade-code-keyword"> self</span> = [ <span class="macmade-code-keyword">super</span> init ] ) ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> }</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">return self</span>;</code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )dealloc</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> [ <span class="macmade-code-keyword">super</span> dealloc ];</code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source">- ( <span class="macmade-code-predefined">uint64_t</span> )timeIdle</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">return</span> 0;</code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source">- ( <span class="macmade-code-predefined">NSUInteger</span> )secondsIdle</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">uint64_t</span> time;</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> time = <span class="macmade-code-keyword">self</span>.<span class="macmade-code-ctag">timeIdle</span>;</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">return</span> ( <span class="macmade-code-predefined">NSUInteger</span> )( time &gt;&gt; 30 );</code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>Nous avons une méthode &#8220;init&#8221;, qui nous servira à établir la communication de base avec I/O Kit, une méthode &#8220;dealloc&#8221; qui nous permettra de libérer les ressources que nous avons alloués, et une méthode (getter) pour chacune de nos propriétés.</div>
<div>La seconde (secondsIdle) ne fait que prendre le temps en nanosecondes et le convertir en secondes. Pour ce faire, il suffit de diviser le temps par 10 puissance 9. Puisque nous avons des valeurs entières, un décalage de 30 sur la droite reviens exactement au même résultat (en plus rapide bien sûr).</div>
<div>Nous allons maintenant nous concentrer sur la méthode &#8220;init&#8221;, et établir une communication avec I/O Kit, qui nous permettra d&#8217;obtenir des informations sur le matériel.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )init</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">kern_return_t</span> status;</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">if</span>( ( <span class="macmade-code-keyword">self</span> = [ <span class="macmade-code-keyword">super</span> init ] ) ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> }</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-keyword">return self</span>;</code><br />
<code class="macmade-source">}</code></div>
<div>Nous déclarons une variable de type &#8220;kern_status&#8221;, qui nous permettra de connaître le status de la communication avec I/O Kit, afin de gérer d&#8217;éventuelles erreurs.<br />
La suite de code se passe à l&#8217;intérieur de l&#8217;instruction &#8220;if&#8221;:</div>
<div class="macmade-code"><code class="macmade-source">status = <span class="macmade-code-predefined">IOMasterPort</span>( <span class="macmade-code-keyword">MACH_PORT_NULL</span>, &amp;<span class="macmade-code-ctag">ioPort</span> );</code></div>
<div>Ici, nous établissons la connexion avec I/O Kit, sur le port par défaut (MACH_PORT_NULL).</div>
<div>Pour contrôler le résultat de l&#8217;opération, nous pouvons comparer la valeur de &#8220;status&#8221; avec &#8220;KERN_SUCCESS&#8221;:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">if</span>( status != <span class="macmade-code-keyword">KERN_SUCCESS</span> ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-comment">/* Error management... */</span></code><br />
<code class="macmade-source">}</code></div>
<div>I/O Kit se compose de plusieurs services. Celui qui nous intéresse est &#8220;IOHID&#8221; (I/O Human Interface Driver). C&#8217;est celui qui nous permettra de connaître l&#8217;état de l&#8217;interaction entre l&#8217;utilisateur et la machine.<br />
Nous récupérons dans le code suivant un itérateur sur les services I/O Kit, qui nous servira à accéder à IOHID.</div>
<div class="macmade-code"><code class="macmade-source">status = <span class="macmade-code-predefined">IOServiceGetMatchingServices</span>(</code><br />
<code class="macmade-source"> <span class="macmade-code-ctag">ioPort</span>,</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined"> IOServiceMatching</span>( <span class="macmade-code-string">"IOHIDSystem"</span> ),</code><br />
<code class="macmade-source"> &amp;<span class="macmade-code-ctag">ioIterator</span></code><br />
<code class="macmade-source">);</code></div>
<div>Nous pouvons maintenant stocker notre service IOHID:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-ctag">ioObject</span> = <span class="macmade-code-predefined">IOIteratorNext</span>( <span class="macmade-code-ctag">ioIterator</span> );</code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">if</span> ( <span class="macmade-code-ctag">ioObject</span> == 0 ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-comment">/* Error management */</span></code><br />
<code class="macmade-source">}</code></p>
<p><code class="macmade-source"><span class="macmade-code-predefined">IOObjectRetain</span>( <span class="macmade-code-ctag">ioObject</span> );</code><br />
<code class="macmade-source"><span class="macmade-code-predefined">IOObjectRetain</span>( <span class="macmade-code-ctag">ioIterator</span> );</code></div>
<div>Nos effectuons ici un &#8220;retain&#8221;, pour s&#8217;assurer que nos objets ne seront pas désalloués automatiquement.<br />
Il ne faut donc pas oublier d&#8217;effectuer un &#8220;release&#8221; dans la méthode &#8220;dealloc&#8221;:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )dealloc</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">IOObjectRelease</span>( <span class="macmade-code-ctag">ioObject</span> );</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">IOObjectRelease</span>( <span class="macmade-code-ctag">ioIterator</span> );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> [ <span class="macmade-code-keyword">super</span> dealloc ];</code><br />
<code class="macmade-source">}</code></div>
<div>Nous avons donc maintenant établi la communication avec I/O Kit, et obtenu un accès au service IOHID.<br />
Il ne nous reste plus qu&#8217;à interroger ce service, dans la méthode &#8220;timeIdle&#8221;.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-predefined">uint64_t</span> )timeIdle</code><br />
<code class="macmade-source">{</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">kern_return_t</span> status;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFTypeRef</span> idle;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFTypeID</span> type;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">uint64_t</span> time;</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFMutableDictionaryRef</span> properties;</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> properties = <span class="macmade-code-keyword">NULL</span>;</code></div>
<div>Nous déclarons ici les différentes variables que nous allons utiliser.</div>
<div>Nous allons en premier lieu récupérer les propriétés de IOHID.</div>
<div class="macmade-code"><code class="macmade-source">status = <span class="macmade-code-predefined">IORegistryEntryCreateCFProperties</span>(</code><br />
<code class="macmade-source"> <span class="macmade-code-ctag">ioObject</span>,</code><br />
<code class="macmade-source"> &amp;properties,</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">kCFAllocatorDefault</span>,</code><br />
<code class="macmade-source"> 0</code><br />
<code class="macmade-source">);</code></div>
<div>Nous récupérons ici dans notre variable &#8220;properties&#8221; un dictionnaire, comparable à l&#8217;objet &#8220;NSDictionnary&#8221;.<br />
Nous récupérons également toujours un status du kernel, qu&#8217;il nous faut vérifier comme précédemment.</div>
<div>Nous pouvons donc désormais obtenir un propriété de IOHID. Celle qui nous intéresse se nomme &#8220;HIDIdleTime&#8221;:</div>
<div class="macmade-code"><code class="macmade-source">idle = <span class="macmade-code-predefined">CFDictionaryGetValue</span>( properties, <span class="macmade-code-keyword">CFSTR</span>( <span class="macmade-code-string">"HIDIdleTime"</span> ) );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"><span class="macmade-code-keyword">if</span>( !idle ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFRelease</span>( ( <span class="macmade-code-predefined">CFTypeRef</span> )properties );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-comment">/* Error management */</span></code><br />
<code class="macmade-source">}</code></div>
<div>En cas d&#8217;erreur, il ne faut pas oublier de releaser l&#8217;objet &#8220;properties&#8221;, afin d&#8217;éviter un memory leak.</div>
<div>Un dictionnaire peut contenir plusieurs types de valeurs. Nous devons donc connaître le type de la propriété &#8220;HIDIdleTime&#8221; avant de la traiter.</div>
<div class="macmade-code"><code class="macmade-source">type = <span class="macmade-code-predefined">CFGetTypeID</span>( idle );</code></div>
<div>La propriété peut être de type &#8220;number&#8221; ou &#8220;data&#8221;. Pour obtenir la valeur correcte, chaque cas doit être pris en compte.</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">if</span>( type == <span class="macmade-code-predefined">CFDataGetTypeID()</span> ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFDataGetBytes</span>( ( <span class="macmade-code-predefined">CFDataRef</span> )idle, <span class="macmade-code-predefined">CFRangeMake</span>( 0, <span class="macmade-code-keyword">sizeof</span>( time ) ), ( <span class="macmade-code-predefined">UInt8</span> * )&amp;time );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source">} <span class="macmade-code-keyword">else if</span>( type == <span class="macmade-code-predefined">CFNumberGetTypeID()</span> ) {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFNumberGetValue</span>( ( <span class="macmade-code-predefined">CFNumberRef</span> )idle, <span class="macmade-code-predefined">kCFNumberSInt64Type</span>, &amp;time );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source">} <span class="macmade-code-keyword">else</span> {</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFRelease</span>( idle );</code><br />
<code class="macmade-source"> <span class="macmade-code-predefined">CFRelease</span>( ( <span class="macmade-code-predefined">CFTypeRef</span> )properties );</code><br />
<code class="macmade-source"> </code><br />
<code class="macmade-source"> <span class="macmade-code-comment">/* Error management */</span></code><br />
<code class="macmade-source">}</code></div>
<div>Il ne reste plus qu&#8217;à releaser nos objets, et à retourner la valeur:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-predefined">CFRelease</span>( idle );</code><br />
<code class="macmade-source"><span class="macmade-code-predefined">CFRelease</span>( ( <span class="macmade-code-predefined">CFTypeRef</span> )properties );</code></p>
<p><code class="macmade-source"><span class="macmade-code-keyword">return</span> time;</code></div>
<div>La classe est terminée. Pour l&#8217;utiliser, il suffit de l&#8217;instancier et de consulter sa propriété &#8220;secondsIdle&#8221; (depuis un timer par exemple).</div>
<h3>Demo</h3>
<div>Voici un exemple de programme utilisant cette classe pour afficher l&#8217;inactivité:</div>
<div><a href="/wp-content/uploads/macmade/idle.m">idle.m</a></div>
<div>Pour le compiler et l&#8217;executer:</div>
<div class="macmade-code"><code class="macmade-source">gcc -Wall -framework Cocoa -framework IOKit -o idle idle.m &amp;&amp; ./idle</code></div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2010/02/09/mac-iphone-ipad-detecter-linactivite-de-lutilisateur-avec-io-kit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TYPO3 et Campaign Monitor</title>
		<link>http://blog.netinfluence.com/2010/01/04/typo3-et-campaign-monitor/</link>
		<comments>http://blog.netinfluence.com/2010/01/04/typo3-et-campaign-monitor/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 15:01:23 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[newsletter]]></category>
		<category><![CDATA[Online PR & communication]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[typo3]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=522</guid>
		<description><![CDATA[Pour les utilisateurs du CMS TYPO3 et du service Campaign Monitor, netinfluence vient de publier une extension TYPO3 permettant l'enregistrement d'une adresse email dans une liste gérée par Campaign Monitor depuis le frontend TYPO3.]]></description>
			<content:encoded><![CDATA[<div>Pour les utilisateurs du CMS <a href="http://typo3.org/">TYPO3</a> et du service <a href="http://www.campaignmonitor.com/">Campaign Monitor</a>, netinfluence vient de publier une extension TYPO3 permettant l&#8217;enregistrement d&#8217;une adresse email dans une liste gérée par Campaign Monitor depuis le frontend TYPO3.</p>
<p>Cette extension peut-être <a href="http://typo3.org/extensions/repository/view/netmailing/current/">téléchargée</a> depuis le site officiel de TYPO3.</p>
<p>La <a href="http://typo3.org/documentation/document-library/extension-manuals/netmailing/1.0.0/view/">documentation</a> est également disponible directement en ligne.</p>
</div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2010/01/04/typo3-et-campaign-monitor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Closure et fonctions lambda en Objective-C</title>
		<link>http://blog.netinfluence.com/2009/11/12/closure-et-fonctions-lambda-en-objective-c/</link>
		<comments>http://blog.netinfluence.com/2009/11/12/closure-et-fonctions-lambda-en-objective-c/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 22:02:00 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[avant-garde]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[communauté]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[méthodes]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=55</guid>
		<description><![CDATA[De nombreux langages de scripts permettent l'utilisation de «fonctions lambdas», ou encore «fonctions anonymes», concept généralement lié au phénomène appelé «closure».<br />
 Il s'agit de concepts bien connus notamment en JavaScript, ActionScript, ou encore en PHP depuis sa version 5.3.<br />
 Le langage Objective-C offre depuis peu une implémentation de ces deux concepts, appelée «blocks».<br />
 Les blocks sont disponibles depuis Mac OS X 10.6 et l'adoption de Clang.]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small"> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a href="http://www.gnu.org/copyleft/fdl.html" title="Free Documentation License">http://www.gnu.org/copyleft/fdl.html</a></div>
</div>
<h3>Définitions</h3>
<div>
De nombreux langages de scripts permettent l&#8217;utilisation de «fonctions lambdas», ou encore «fonctions anonymes», concept généralement lié au phénomène appelé «closure».<br />
 Il s&#8217;agit de concepts bien connus notamment en JavaScript, ActionScript, ou encore en PHP depuis sa version 5.3.<br />
 Le langage Objective-C offre depuis peu une implémentation de ces deux concepts, appelée «blocks».<br />
 Les blocks sont disponibles depuis Mac OS X 10.6 et l&#8217;adoption de Clang.
</div>
<p><span id="more-55"></span></p>
<h4>Fonctions anonymes</h4>
<div> Comme son nom l&#8217;indique, une fonction anonyme est une fonction ne possédant pas de nom, ou d&#8217;identifiant. Elle ne contient que son contenu (body), et peut être associée à une variable, pour être ré-utilisée, ou passée en argument d&#8217;une autre fonction. </div>
<div> Ce phénomène est très souvent utilisé dans des langages de scripts, notamment pour des callbacks. </div>
<div> En JavaScript par exemple, imaginons une fonction standard nommée «foo», prenant en paramètre un callback, et l&#8217;exécutant dans son body: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">function</span> foo( callback )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    callback();</code><br />
 <code class="macmade-source">}</code> </div>
<div> Il est parfaitement possible de définir une autre fonction standard, et de la passer en paramètre de notre première fonction: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">function</span> bar()</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    alert( <span class="macmade-code-string">'Hello World!'</span> );</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source">foo( bar );</code> </div>
<div> Le problème dans un tel cas est que nous déclarons une fonction nommée «bar» dans le scope global. Il en découle un risque de collision avec une éventuelle autre fonction qui porterait le même nom. </div>
<div> Le langage JavaScript nous permet donc de déclarer la fonction utilisée comme callback lors de l&#8217;appel: </div>
<div class="macmade-code"> <code class="macmade-source">foo(</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">function</span>()</code><br />
 <code class="macmade-source">    {</code><br />
 <code class="macmade-source">        alert( <span class="macmade-code-string">'Hello World!'</span> );</code><br />
 <code class="macmade-source">    }</code><br />
 <code class="macmade-source">);</code> </div>
<div> Notre callback n&#8217;a ici pas d&#8217;identifiant. Il n&#8217;existera pas dans le scope global, et donc ne risquera pas d&#8217;entrer en conflit avec une fonction existante. </div>
<div> Il est également possible de définir le callback comme variable. Il n&#8217;existera toujours pas dans le scope global, mais pourra ainsi être ré-utilisé à volonté via cette variable: </div>
<div class="macmade-code"> <code class="macmade-source">myCallback = <span class="macmade-code-keyword">function</span>()</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    alert( <span class="macmade-code-string">'Hello World!'</span> );</code><br />
 <code class="macmade-source">};</code></p>
<p> <code class="macmade-source">foo( myCallback );</code> </div>
<h4>Closure</h4>
<div> Le phénomène appelé «closure» consiste en la possibilité, pour une fonction, d&#8217;accéder aux variables disponibles dans son contexte de déclaration, ceci même dans le cas où son contexte d&#8217;exécution est différent. </div>
<div> Toujours en JavaScript, imaginons le code suivant: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">function</span> foo( callback )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    alert( callback() );</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">function</span> bar()</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">var</span> str = <span class="macmade-code-string">'Hello World'</span>;</code></p>
<p> <code class="macmade-source">    foo(</code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">function</span>()</code><br />
 <code class="macmade-source">        {</code><br />
 <code class="macmade-source">            <span class="macmade-code-keyword">return</span> str;</code><br />
 <code class="macmade-source">        }</code><br />
 <code class="macmade-source">    );</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source">bar();</code> </div>
<div> Notre callback, passé à la fonction «foo» depuis le contexte d&#8217;exécution de le fonction «bar» retourne une variable nommée «str».<br />
 Or, cette variable, déclarée dans le contexte de la fonction «bar», est une variable locale à cette dernière. Autrement dit, elle n&#8217;existe qu&#8217;à l&#8217;intérieur de ce contexte.<br />
 Comme notre callback est exécuté depuis un contexte différent du contexte de la déclaration de cette variable, on pourrait penser que le code-ci dessus n&#8217;affiche rien.<br />
 Mais c&#8217;est ici que le phénomène de closure intervient.<br />
 Quel que soit son contexte d&#8217;exécution, une fonction conserve un accès aux variables disponibles lors de sa déclaration. </div>
<div> Notre callback aura donc bien accès à la variable «str», même s&#8217;il est effectivement appelé depuis la fonction «foo», et que cette dernière n&#8217;y a pas accès. </div>
<h3>Implémentation en Objective-C</h3>
<div> Objective-C implémente ce genre de concepts, même s&#8217;il existe un certain nombre de subtilités, venant du fait qu&#8217;il s&#8217;agit d&#8217;un langage compilé dérivé du C, en restant très proche, donc très différent d&#8217;un langage de script interprété. </div>
<div> Il est à noter que le support des blocks est aussi disponible en C pur, ou en C++ (et donc en Objective-C++). </div>
<div> De même qu&#8217;une fonction standard en C, la déclaration d&#8217;un block (fonction anonyme) se doit d&#8217;être précédée par la déclaration de son prototype. </div>
<div> La syntaxe de déclaration d&#8217;un block n&#8217;est pas la plus évidente, mais on s&#8217;y fait relativement vite.<br />
 Voici par exemple le prototype d&#8217;un block: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-predefined">NSString</span> * ( ^myBlock )( <span class="macmade-code-keyword">int</span> );</code> </div>
<div> Nous déclarons ici le prototype d&#8217;un block («^»), destiné à être nommé «myBlock», prenant un argument unique de type «int», et retournant un pointeur sur un objet de type «NSString». </div>
<div> Nous pouvons maintenant déclarer le block: </div>
<div class="macmade-code"> <code class="macmade-source">myBlock = ^( <span class="macmade-code-keyword">int</span> number )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">return</span> [ <span class="macmade-code-predefined">NSString stringWithFormat</span>: <span class="macmade-code-string">@"Passed number: %i"</span>, number ];</code><br />
 <code class="macmade-source">};</code> </div>
<div> Nous assignons donc à la variable «myBlock» le body d&#8217;une fonction, prenant comme argument «number» un entier. Cette fonction retourne un objet «NSString», dans lequel sera affiché cet entier. </div>
<div> <strong>Attention, ne pas oublier le point virgule à la fin de la déclaration du block!</strong> </div>
<div> Si cela est facultatif dans des langages de scripts, c&#8217;est absolument nécessaire pour un langage compilé comme Objective-C.<br />
 L&#8217;oublier résulterait en une erreur du compilateur, qui refuserait de générer l&#8217;exécutable final. </div>
<div> Le block peut désormais être utilisé, comme une fonction standard: </div>
<div class="macmade-code"> <code class="macmade-source">myBlock();</code> </div>
<div> Voici le code complet d&#8217;un programme Objective-C, reprenant l&#8217;exemple précédent: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">&lt;Cocoa/Cocoa.h&gt;</span></code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">int</span> main( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSAutoreleasePool</span> * pool;</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSString</span>          * ( ^myBlock )( <span class="macmade-code-keyword">int</span> );</code></p>
<p> <code class="macmade-source">    pool    = [ [ <span class="macmade-code-predefined">NSAutoreleasePool</span> alloc ] init ];</code><br />
 <code class="macmade-source">    myBlock = ^( <span class="macmade-code-keyword">int</span> number )</code><br />
 <code class="macmade-source">    {</code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">return</span> [ <span class="macmade-code-predefined">NSString stringWithFormat</span>: <span class="macmade-code-string">@"Passed number: %i"</span>, number ];</code><br />
 <code class="macmade-source">    };</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"%@"</span>, myBlock() );</code></p>
<p> <code class="macmade-source">    [ pool release ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> EXIT_SUCCESS;</code><br />
 <code class="macmade-source">}</code> </div>
<div> Un tel programme peut être compilé à l&#8217;aide de la commande suivante (Terminal): </div>
<div class="macmade-code"> <code class="macmade-source">gcc -Wall -framework Cocoa -o test test.m</code> </div>
<div> Cela générera un fichier exécutable nommé «test», à partir du fichier source «test.m».<br />
 Pour lancer l&#8217;exécutable: </div>
<div class="macmade-code"> <code class="macmade-source">./test</code> </div>
<div> La déclaration du prototype d&#8217;un block peut être omise dans le cas où le block n&#8217;est pas assigné à une variable, comme par exemple s&#8217;il est transmis directement comme argument. </div>
<div> Par exemple: </div>
<div class="macmade-code"> <code class="macmade-source">someFunction( ^ <span class="macmade-code-predefined">NSString</span> * ( <span class="macmade-code-keyword">void</span> ) { <span class="macmade-code-keyword">return</span> <span class="macmade-code-string">@"Hello World!"</span> } );</code> </div>
<div> Il est à noter que dans un tel cas, le type de retour doit être déclaré. Ici, il s&#8217;agit d&#8217;un objet de type «NSString». </div>
<h4>Passage d&#8217;un block comme argument</h4>
<div> Un block peut bien sûr être passé comme argument d&#8217;une fonction C.<br />
 Là aussi, la syntaxe peut être quelque peu déroutante à première vue: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">void</span> logBlock( <span class="macmade-code-predefined">NSString</span> * ( ^theBlock )( <span class="macmade-code-keyword">int</span> ) )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"Block returned: %@"</span>, theBlock() );</code><br />
 <code class="macmade-source">}</code> </div>
<div> Evidemment, comme Objective-C est un langage fortement typé, une fonction recevant un block en argument doit également déclarer son type de retour et le type de ses éventuels arguments. </div>
<div> Il en va de même dans le cas d&#8217;une méthode d&#8217;une classe Objective-C: </div>
<div class="macmade-code"> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )logBlock: ( <span class="macmade-code-predefined">NSString</span> * ( ^ )( <span class="macmade-code-keyword">int</span> ) )theBlock;</code> </div>
<h4>Closure</h4>
<div> Le phénomène de closure est également présent en Objective-C, même si son comportement est évidemment différent de celui des langages interprétés. </div>
<div> Imaginons le programme suivant: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">&lt;Cocoa/Cocoa.h&gt;</span></code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">void</span> logBlock( <span class="macmade-code-keyword">int</span> ( ^theBlock )( <span class="macmade-code-keyword">void</span> ) )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"Closure var X: %i"</span>, theBlock() );</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">int</span> main( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSAutoreleasePool</span> * pool;</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">int</span> ( ^myBlock )( <span class="macmade-code-keyword">void</span> );</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">int</span> x;</code></p>
<p> <code class="macmade-source">    pool = [ [ <span class="macmade-code-predefined">NSAutoreleasePool</span> alloc ] init ];</code><br />
 <code class="macmade-source">    x    = 27;</code></p>
<p> <code class="macmade-source">    myBlock = ^( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">    {</code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">return</span> x;</code><br />
 <code class="macmade-source">    };</code></p>
<p> <code class="macmade-source">    logBlock( myBlock );</code></p>
<p> <code class="macmade-source">    [ pool release ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> EXIT_SUCCESS;</code><br />
 <code class="macmade-source">}</code> </div>
<div> La fonction «main» déclare un entier, de valeur 27, ainsi qu&#8217;un block, retournant cette même variable.<br />
 Le block set ensuite passé à la fonction «logBlock», qui affiche sa valeur de retour. </div>
<div> Même dans le contexte d&#8217;exécution de la fonction «logBlock», le block déclaré dans la fonction «main» continue d&#8217;avoir accès à l&#8217;entier «x», et peut donc sans aucun problème en retourner la valeur. </div>
<div> Il est à noter que les blocks ont également accès aux variable globales, même statiques si elles sont disponibles dans le contexte du block. </div>
<div> Il existe ici une première subtilité. En effet, les variables disponibles depuis un block par le phénomène de closure sont de type «const». Autrement dit, elle ne peuvent être modifiées depuis l&#8217;intérieur du block. </div>
<div> Par exemple, imaginons que notre block incrémente la valeur de x avant de la retourner: </div>
<div class="macmade-code"> <code class="macmade-source">myBlock = ^( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    x++</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> x;</code><br />
 <code class="macmade-source">};</code> </div>
<div> Le compilateur refusera ici de compiler le programme, puisque la variable «x» n&#8217;est disponible qu&#8217;en lecture pour notre block. </div>
<div> Pour qu&#8217;une variable puisse être modifiée depuis un block, il faut la déclarer avec le mot clé «__block».<br />
 Ainsi, le codé précédent est valide si l&#8217;on déclare la variable x ainsi: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">__block</span> <span class="macmade-code-keyword">int</span> x;</code> </div>
<h4>Gestion de la mémoire</h4>
<div> Au niveau C, un block est une structure, pouvant être copiée et détruite.<br />
 Deux fonctions C sont à disposition pour cet usage: «Block_copy()» et «Block_destroy».<br />
 En Objective-C, un block peut également recevoir les messages «retain», «release» et «copie», comme un objet. </div>
<div> C&#8217;est aspect peut-être extrêmement important dans le cas où un block doit être conservé pour une utilisation ultérieure (et par exemple stocké dans une propriété d&#8217;une classe). </div>
<div> Ne pas copier le block, ou ne pas effectuer de «retain» dans un tel cas peut en effet induire une erreur de segmentation. </div>
<h4>Exemple d&#8217;utilisation</h4>
<div> Les blocks peuvent être utilisés dans de très nombreux contextes, afin de simplifier le code, et réduire le nombre de fonctions déclarées. </div>
<div> Voici un exemple simple illustrant l&#8217;utilisation des blocks. </div>
<div> Nous allons ajouter à la classe «NSArray» une méthode statique permettant de générer un tableau en filtrant les éléments d&#8217;un autre tableau, à l&#8217;aide d&#8217;un callback. </div>
<div> Pour les amateurs de PHP, il s&#8217;agit ici d&#8217;un équivalent de la fonction «array_filter()». </div>
<div> Nous allons commencer par la déclaration d&#8217;une catégorie de la classe «NSArray». Pour rappel, une catégorie permet l&#8217;ajout de méthodes dans une classe existante, évitant ainsi le besoin de créer une sous-classe.</div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">@interface</span> <span class="macmade-code-predefined">NSArray</span>( BlockExample )</code></p>
<p> <code class="macmade-source">+ ( <span class="macmade-code-predefined">NSArray</span> * )arrayByFilteringArray: ( <span class="macmade-code-predefined">NSArray</span> * )source withCallback: ( <span class="macmade-code-keyword">BOOL</span> ( ^ )( <span class="macmade-code-keyword">id</span> ) )callback;</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code> </div>
<div> Nous déclarons ici une méthode retournant un objet de type «NSArray», et prenant en argument un autre objet «NSArray», ainsi qu&#8217;un callback, sous forme de block. </div>
<div> Ce callback sera exécuté pour chaque élément du tableau passé en argument. Il doit retourner une valeur booléenne, afin de savoir si l&#8217;élément courant du tableau source doit être conservé dans le tableau retourné. Le block prend donc comme unique argument l&#8217;objet courant du tableau source. </div>
<div> Voyons maintenant l&#8217;implémentation de cette méthode: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> <span class="macmade-code-predefined">NSArray</span>( BlockExample )</code></p>
<p> <code class="macmade-source">+ ( <span class="macmade-code-predefined">NSArray</span> * )arrayByFilteringArray: ( <span class="macmade-code-predefined">NSArray</span> * )source withCallback: ( <span class="macmade-code-keyword">BOOL</span> ( ^ )( <span class="macmade-code-keyword">id</span> ) )callback</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSMutableArray</span> * result;</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">id</span>               element;</code></p>
<p> <code class="macmade-source">    result = [ <span class="macmade-code-predefined">NSMutableArray</span> <span class="macmade-code-predefined">arrayWithCapacity</span>: [ source count ] ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">for</span>( element <span class="macmade-code-keyword">in</span> source ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-keyword">if</span>( callback( element ) == <span class="macmade-code-keyword">YES</span> ) {</code></p>
<p> <code class="macmade-source">            [ result <span class="macmade-code-predefined">addObject</span>: element ];</code><br />
 <code class="macmade-source">        }</code><br />
 <code class="macmade-source">    }</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> result;</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code> </div>
<div> Nous créons en premier lieu un tableau de taille dynamique («NSMutableArray»), en lui allouant une capacité initiale correspondant au nombre d&#8217;entrées du tableau source. </div>
<div> Ensuite, nous itérons chaque élément du tableau source, et nous ajoutons l&#8217;élément courant dans le cas où le résultat du callback retourne la valeur booléenne «YES». </div>
<div> Voici un exemple de programme utilisant une telle méthode.<br />
 Ici, nous nous servons du callback pour créer un tableau ne contenant que les objets de type «NSString» du tableau source: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-keyword">#import</span> <span class="macmade-code-string">&lt;Cocoa/Cocoa.h&gt;</span></code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@interface</span> <span class="macmade-code-predefined">NSArray</span>( BlockExample )</code></p>
<p> <code class="macmade-source">+ ( <span class="macmade-code-predefined">NSArray</span> * )arrayByFilteringArray: ( <span class="macmade-code-predefined">NSArray</span> * )source withCallback: ( <span class="macmade-code-keyword">BOOL</span> ( ^ )( <span class="macmade-code-keyword">id</span> ) )callback;</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> <span class="macmade-code-predefined">NSArray</span>( BlockExample )</code></p>
<p> <code class="macmade-source">+ ( <span class="macmade-code-predefined">NSArray</span> * )arrayByFilteringArray: ( <span class="macmade-code-predefined">NSArray</span> * )source withCallback: ( <span class="macmade-code-keyword">BOOL</span> ( ^ )( <span class="macmade-code-keyword">id</span> ) )callback</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSMutableArray</span> * result;</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">id</span>               element;</code></p>
<p> <code class="macmade-source">    result = [ <span class="macmade-code-predefined">NSMutableArray</span> <span class="macmade-code-predefined">arrayWithCapacity</span>: [ source count ] ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">for</span>( element <span class="macmade-code-keyword">in</span> source ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-keyword">if</span>( callback( element ) == <span class="macmade-code-keyword">YES</span> ) {</code></p>
<p> <code class="macmade-source">            [ result <span class="macmade-code-predefined">addObject</span>: element ];</code><br />
 <code class="macmade-source">        }</code><br />
 <code class="macmade-source">    }</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> result;</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></p>
<p> <code class="macmade-source"><span class="macmade-code-keyword">int</span> main( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSAutoreleasePool</span> * pool;</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSArray</span>           * array1;</code><br />
 <code class="macmade-source">    <span class="macmade-code-predefined">NSArray</span>           * array2;</code></p>
<p> <code class="macmade-source">    pool   = [ [ <span class="macmade-code-predefined">NSAutoreleasePool</span> alloc ] init ];</code><br />
 <code class="macmade-source">    array1 = [ <span class="macmade-code-predefined">NSArray</span> <span class="macmade-code-predefined">arrayWithObjects</span>: <span class="macmade-code-string">@"Hello World!"</span>, [ <span class="macmade-code-predefined">NSDate</span> date ], <span class="macmade-code-string">@"Hello Universe!"</span>, <span class="macmade-code-keyword">nil</span> ];</code><br />
 <code class="macmade-source">    array2 = [ <span class="macmade-code-predefined">NSArray</span></code><br />
 <code class="macmade-source">                    <span class="macmade-code-ctag">arrayByFilteringArray</span>: array1</code><br />
 <code class="macmade-source">                    <span class="macmade-code-ctag">withCallback</span>: ^ <span class="macmade-code-keyword">BOOL</span> ( <span class="macmade-code-keyword">id</span> element )</code><br />
 <code class="macmade-source">                    {</code><br />
 <code class="macmade-source">                        <span class="macmade-code-keyword">return</span> [ element <span class="macmade-code-predefined">isKindOfClass</span>: [ <span class="macmade-code-predefined">NSString</span> class ] ];</code><br />
 <code class="macmade-source">                    }</code><br />
 <code class="macmade-source">             ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"%@"</span>, array2 );</code></p>
<p> <code class="macmade-source">    [ pool release ];</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-keyword">return</span> EXIT_SUCCESS;</code><br />
 <code class="macmade-source">}</code></div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2009/11/12/closure-et-fonctions-lambda-en-objective-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Comprendre les nombres à virgule flottante</title>
		<link>http://blog.netinfluence.com/2009/09/24/comprendre-les-nombres-a-virgule-flottante/</link>
		<comments>http://blog.netinfluence.com/2009/09/24/comprendre-les-nombres-a-virgule-flottante/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 08:55:00 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[Développement]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=53</guid>
		<description><![CDATA[<p>Les nombres à virgule flottante à précision simple sont le plus souvent appelés 'float' ou 'real'. Cet article explique comment ces nombres sont gérés par un ordinateur, au niveau binaire.</p>]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small"> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a href="http://www.gnu.org/copyleft/fdl.html" title="Free Documentation License">http://www.gnu.org/copyleft/fdl.html</a> </div>
</p></div>
<h2>Représentation binaire des nombres à virgule flottante à précision simple</h2>
<div> Les nombres à virgule flottante à précision simple sont le plus souvent appelés &#8216;float&#8217; ou &#8216;real&#8217;. Ils sont longs de 4 bytes, et sont formés de la manière suivante, de gauche à droite: </div>
<div>
<ul>
<li>Signe:    1 bit</li>
<li>Exposant: 8 bits</li>
<li>Mantisse: 23 bits</li>
</ul></div>
<div>
<table class="macmade">
<tbody>
<tr>
<td>X</td>
<td>XXXX XXXX</td>
<td>XXX XXXX XXXX XXXX XXXX XXXXX</td>
</tr>
<tr>
<th>Signe<br />1 bit</th>
<th>Exposant<br />8 bits</th>
<th>Mantisse<br />23 bits</th>
</tr>
</tbody>
</table></div>
<div> Le signe indique si le nombre est positif ou négatif (zéro pour les nombres positifs et un pour les négatifs). </div>
<div> L&#8217;exposant réel est calculé en soustrayant 127 à la valeur du champ exposant. Il s&#8217;agit de l&#8217;exposant du nombre, tel qu&#8217;exprimé en notation scientifique. </div>
<div> La mantisse complète, parfois aussi appelée significande, doit être considérée comme une valeur sur 24 bits. En effet, comme nous utilisons la notation scientifique, il y a un premier bit implicite (appelé parfois le bit caché) dont la valeur est fixée à 1, étant donné qu&#8217;il n&#8217;y a jamais de 0 en tout premier, en notation scientifique.<br />
 Par exemple, on ne dira jamais <code class="macmade">0.123 · 10<span class="macmade-power">5</span></code> mais bien <code class="macmade">1.23 · 10<span class="macmade-power">4</span></code>. </div>
<div> La conversion est effectuée de la manière suivante: </div>
<div class="macmade-code"> <code class="macmade">-1<span class="macmade-power">S</span> · 1.M · 2<span class="macmade-power">( E - 127 )</span></code> </div>
<div> Où S est le signe, M la mantisse, et E l&#8217;exposant. </div>
<h3>2. Exemple</h3>
<div> Prenons par exemple <code class="macmade">0100 0000 1011 1000 0000 0000 0000 0000</code>, ou <code class="macmade">0x40B80000</code> en notation hexadécimale. </div>
<div>
<table class="macmade">
<tbody>
<tr>
<th>Hexadécimal</th>
<td>4</td>
<td class="macmade-alt">0</td>
<td>B</td>
<td class="macmade-alt">8</td>
<td>0</td>
<td class="macmade-alt">0</td>
<td>0</td>
<td class="macmade-alt">0</td>
</tr>
<tr>
<th>Binaire</th>
<td>0100</td>
<td class="macmade-alt">0000</td>
<td>1011</td>
<td class="macmade-alt">1000</td>
<td>0000</td>
<td class="macmade-alt">0000</td>
<td>0000</td>
<td class="macmade-alt">0000</td>
</tr>
</tbody>
</table></div>
<div>
<table class="macmade">
<tbody>
<tr>
<th>Signe</th>
<th>Exposant</th>
<th>Mantisse</th>
</tr>
<tr>
<td>0</td>
<td>1000 0001</td>
<td>(1) 011 1000 0000 0000 0000 0000</td>
</tr>
</tbody>
</table></div>
<div>
<ul>
<li>Le signe est <code class="macmade">0</code>, le nombre est donc positif.</li>
<li>Le champ exposant est <code class="macmade">1000 0001</code>, autrement dit 129 en décimal. La valeur réelle de l&#8217;exposant est donc 129 &#8211; 127, ce qui nous donne 2.</li>
<li>La mantisse, avec le premier bit implicite, est <code class="macmade">1011 1000 0000 0000 0000 0000</code>.</li>
</ul></div>
<div> La représentation finale du nombre en notation scientifique binaire est donc: </div>
<div class="macmade-code"> <code class="macmade">-1<span class="macmade-power">0</span> · 1.0111 · 2<span class="macmade-power">2</span></code> </div>
<div> Mathématiquement, cela veut dire: </div>
<div class="macmade-code"> <code class="macmade">1 · ( 1 · 2<span class="macmade-power">0</span> + 0 · 2<span class="macmade-power">-1</span> + 1 · 2<span class="macmade-power">-2</span> + 1 · 2<span class="macmade-power">-3</span> + 1 · 2<span class="macmade-power">-4</span> ) · 2<span class="macmade-power">2</span></code><br />
 <code class="macmade">( 2<span class="macmade-power">0</span> + 2<span class="macmade-power">-2</span> + 2<span class="macmade-power">-3</span> + 2<span class="macmade-power">-4</span> ) · 2<span class="macmade-power">2</span></code><br />
 <code class="macmade">2<span class="macmade-power">2</span> + 2<span class="macmade-power">0</span> + 2<span class="macmade-power">-1</span> + 2<span class="macmade-power">-2</span></code><br />
 <code class="macmade">4 + 1 + 0.5 + 0.25</code> </div>
<div> La valeur du nombre à virgule flottante est donc 5.75. </div>
<h3>3. Nombres spéciaux</h3>
<div> En fonction de la valeur du champ exposant, certain nombres peuvent avoir une valeur spéciale. Ils peuvent être: </div>
<div>
<ul>
<li>Des nombres dénormalisés</li>
<li>Zéro</li>
<li>Infini</li>
<li>NaN (not a number, pas un nombre)</li>
</ul></div>
<h4>3.1. Nombres dénormalisés</h4>
<div> Si la valeur du champ exposant est 0, et que la valeur de la mantisse est plus grande que 0, le nombre doit alors être traité comme un nombre dénormalisé.<br />
 Dans un tel cas, l&#8217;exposant n&#8217;est pas -127, mais -126. Le premier bit implicite, quand à lui, n&#8217;est pas 1 mais 0.<br />
 Cela permet la représentation de nombres plus petits. </div>
<div> La notation scientifique d&#8217;un nombre dénormalisé est: </div>
<div class="macmade-code"> <code class="macmade">-1<span class="macmade-power">S</span> ·  0.M · 2<span class="macmade-power">-126</span></code> </div>
<h4>3.2. Zéro</h4>
<div> Si le champ exposant et la mantisse ont tous deux pour valeur 0, le nombre final est 0. Le bit du signe est autorisé, permettant un zéro positif ou négatif, même si cela n&#8217;a pas un grand sens mathématiquement.<br />
 Il est à noter que zéro peut être considéré comme un nombre dénormalisé. Dans ce cas, cela veut dire <code class="macmade">0 · 2<span class="macmade-power">-126</span></code>, ce que nous donne bien zéro. </div>
<h4>3.3. Infini</h4>
<div> Si la valeur du champ exposant est 255 (les 8 bits définis à 1) et si la valeur de la mantisse est 0, le nombre correspont à l&#8217;infinité, soit posistive ou négative, en fonction du signe. </div>
<h4>3.4. NaN</h4>
<div> Si la valeur du champ exposant est 255 (les 8 bits définis à 1) et si la valeur de la mantisse n&#8217;est pas 0, la valeur ne doit pas être considérée comme un nombre. Dans un tel cas, le signe n&#8217;a aucune signification. </div>
<h3>3. Portée</h3>
<div> La portée est différente pour les nombres normalisés et dénormalisés. La portée pour ces deux cas est indiquée ci-dessous: </div>
<h4>3.1 Nombres normalisés</h4>
<div>
<ul>
<li><strong>Minimum:</strong> <code class="macmade">±1.1754944909521E-38</code> / <code class="macmade">±1.00000000000000000000001<span class="macmade-power">-126</span></code></li>
<li><strong>Maximum:</strong> <code class="macmade">±3.4028234663853E+38</code> / <code class="macmade">±1.11111111111111111111111<span class="macmade-power">128</span></code></li>
</ul></div>
<h4>3.2 Nombres dénormalisés</h4>
<div>
<ul>
<li><strong>Minimum:</strong> <code class="macmade">±1.4012984643248E-45</code> / <code class="macmade">±0.00000000000000000000001<span class="macmade-power">-126</span></code></li>
<li><strong>Maximum:</strong> <code class="macmade">±1.1754942106924E-38</code> / <code class="macmade">±0.11111111111111111111111<span class="macmade-power">-126</span></code></li>
</ul></div>
<h3>4. Exemple de code C</h3>
<div> Voici un exemple de programme C qui converti un nombre binaire en sa représentation en nombre à virgule flottante: </div>
<div class="macmade-code"> <code class="macmade-source"><span class="macmade-code-comment">/* System includes */</span></code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">#include</span> &lt;stdlib.h&gt;</code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">#include</span> &lt;stdio.h&gt;</code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">#include</span> &lt;math.h&gt;</code></p>
<p> <code class="macmade-source"><span class="macmade-code-comment">/* Definition of the boolean data type */</span></code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">typedef</span> <span class="macmade-code-keyword">enum</span> { <span class="macmade-code-keyword">FALSE</span>, <span class="macmade-code-keyword">TRUE</span> } boolean;</code></p>
<p> <code class="macmade-source"><span class="macmade-code-comment">/**</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * Converts a integer to its float representation</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * </span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * This function converts a 32 bits integer to a single precision floating point</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * number, as specified by the IEEE Standard for Floating-Point Arithmetic</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * (IEEE 754). This standard can be found at the folowing address:</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * {@link http://ieeexplore.ieee.org/servlet/opac?punumber=4610933}</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * </span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * @param   unsigned long   The integer to convert to a floating point value</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * @return  float           The floating point number</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * @author                  Jean-David Gadina &lt;macmade@netinfluence.com&gt;</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> */</span></code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">float</span> binaryToFloat( <span class="macmade-code-keyword">unsigned</span> <span class="macmade-code-keyword">long</span> binary )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-comment">/* Gets the sign field */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-comment">/* Bit 0, left to right */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-ctag">boolean</span> sign           = binary &gt;&gt; 31;</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Gets the exponent field */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-comment">/* Bits 1 to 8, left to right */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">unsigned</span> <span class="macmade-code-keyword">char</span> exp      = ( ( binary &gt;&gt; 23 ) &amp; 0xFF );</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Gets the mantissa field */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-comment">/* Bits 9 to 32, left to right */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">unsigned</span> <span class="macmade-code-keyword">long</span> mantissa = ( binary &amp; 0x7FFFFF );</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Storage for the return value */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">float</span> floatValue       = 0;</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Counter */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">signed</span> <span class="macmade-code-keyword">int</span> i           = 0;</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Checks the values of the exponent and the mantissa fields to handle special numbers */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">if</span>( exp == 0 &amp;&amp; mantissa == 0 ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Zero - No need for a computation even if it can be considered as a denormalized number */</span></code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">return</span> 0;</code></p>
<p> <code class="macmade-source">    } <span class="macmade-code-keyword">else</span> <span class="macmade-code-keyword">if</span>( exp == 255 &amp;&amp; mantissa == 0 ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Infinity */</span></code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">return</span> 0;</code></p>
<p> <code class="macmade-source">    } <span class="macmade-code-keyword">else</span> <span class="macmade-code-keyword">if</span>( exp == 255 &amp;&amp; mantissa != 0 ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Not a number */</span></code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">return</span> 0;</code></p>
<p> <code class="macmade-source">    } <span class="macmade-code-keyword">else</span> <span class="macmade-code-keyword">if</span>( exp == 0 &amp;&amp; mantissa != 0 ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Denormalized number - Exponent is fixed to -126 */</span></code><br />
 <code class="macmade-source">        exp = -126;</code></p>
<p> <code class="macmade-source">    } <span class="macmade-code-keyword">else</span> {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Computes the real exponent */</span></code><br />
 <code class="macmade-source">        exp      = exp - 127;</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Adds the implicit bit to the mantissa */</span></code><br />
 <code class="macmade-source">        mantissa = mantissa | 0x800000;</code><br />
 <code class="macmade-source">    }</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Process the 24 bits of the mantissa */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">for</span>( i = 0; i &gt; -24; i-- ) {</code></p>
<p> <code class="macmade-source">        <span class="macmade-code-comment">/* Checks if the current bit is set */</span></code><br />
 <code class="macmade-source">        <span class="macmade-code-keyword">if</span>( mantissa &amp; ( 1 &lt;&lt; ( i + 23 ) ) ) {</code></p>
<p> <code class="macmade-source">            <span class="macmade-code-comment">/* Adds the value for the current bit */</span></code><br />
 <code class="macmade-source">            <span class="macmade-code-comment">/* This is done by computing two raised to the power of the exponent plus the bit position */</span></code><br />
 <code class="macmade-source">            <span class="macmade-code-comment">/* (negative if it's after the implicit bit, as we are using scientific notation) */</span></code><br />
 <code class="macmade-source">            floatValue += ( <span class="macmade-code-keyword">float</span> )<span class="macmade-code-ctag">pow</span>( 2, i + exp );</code><br />
 <code class="macmade-source">        }</code><br />
 <code class="macmade-source">    }</code></p>
<p> <code class="macmade-source">    <span class="macmade-code-comment">/* Returns the final float value */</span></code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">return</span> ( sign == <span class="macmade-code-keyword">FALSE</span> ) ? floatValue : -floatValue;</code><br />
 <code class="macmade-source">}</code></p>
<p> <code class="macmade-source"><span class="macmade-code-comment">/**</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * C main() function</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * </span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> * @return  int     The exit status</span></code><br />
 <code class="macmade-source"><span class="macmade-code-comment"> */</span></code><br />
 <code class="macmade-source"><span class="macmade-code-keyword">int</span> main( <span class="macmade-code-keyword">void</span> )</code><br />
 <code class="macmade-source">{</code><br />
 <code class="macmade-source">    <span class="macmade-code-ctag">printf</span>( <span class="macmade-code-string">"%f\n"</span>, <span class="macmade-code-ctag">binaryToFloat</span>( 0x40B80000 ) );</code><br />
 <code class="macmade-source">    <span class="macmade-code-keyword">return</span> <span class="macmade-code-ctag">EXIT_SUCCESS</span>;</code><br />
 <code class="macmade-source">}</code> </div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2009/09/24/comprendre-les-nombres-a-virgule-flottante/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implémentation d’un système de délégation multiple en Objective-C</title>
		<link>http://blog.netinfluence.com/2009/08/24/implementation-d-un-systeme-de-delegation-multiple-en-objective-c/</link>
		<comments>http://blog.netinfluence.com/2009/08/24/implementation-d-un-systeme-de-delegation-multiple-en-objective-c/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 17:24:00 +0000</pubDate>
		<dc:creator>macmade</dc:creator>
				<category><![CDATA[create]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[tutoriel]]></category>
		<category><![CDATA[wwdc]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://blog.netinfluence.ch/?p=50</guid>
		<description><![CDATA[<p>La délégation est un système présent dans plusieurs classes du framework Cocoa, sous Mac OS X (et donc également sur iPhone OS).<br />
 Ce système permet aux dévelopeurs d'applications Cocoa d'interagir en fonction d'événement précis liés aux fonctionnements intrinsèques des objets Cocoa.</p> <p>De base, le système de délégation ne peut prendre en charge qu'un objet unique. Cet article montre comment implémenter une chaine de délégation dans une classe Objective-C.</p>]]></description>
			<content:encoded><![CDATA[<div class="macmade-grey">
<div class="macmade-small">Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at: <a title="Free Documentation License" href="http://www.gnu.org/copyleft/fdl.html">http://www.gnu.org/copyleft/fdl.html</a></div>
</div>
<h3>1. Qu&#8217;est-ce que la délégation?</h3>
<div>La délégation est un système présent dans plusieurs classes du framework Cocoa, sous Mac OS X (et donc également sur iPhone OS).<br />
Ce système permet aux dévelopeurs d&#8217;applications Cocoa d&#8217;interagir en fonction d&#8217;événement précis liés aux fonctionnements intrinsèques des objets Cocoa.</div>
<div>Prenons par exemple l&#8217;objet NSWindow, qui comme son nom l&#8217;indique permet d&#8217;afficher et de contrôler une fenêtre.</div>
<div>Cet objet fenêtre possède un certain nombre de méthode, comme par exemple &#8216;close&#8217;, ou &#8216;open&#8217;, permettant respectivement d&#8217;ouvrir et de fermer le fenêtre en question.</div>
<div>Lors de la programmation d&#8217;une application Cocoa, il peut être fort utile d&#8217;être informé lors de l&#8217;ouverture ou de la fermeture d&#8217;une fenêtre, pour allouer ou libérer des ressources, terminer des tâches ou des threads, etc.</div>
<div>Le système de délégation du framework Cocoa permet ainsi d&#8217;attacher une instance d&#8217;un objet à un autre objet, le premier ayant la possibilité d&#8217;agir sur le second en fonction de ses différentes phases d&#8217;exécution.</div>
<div>La définition d&#8217;un objet délégué sur un autre objet se passe par convention par la méthode &#8216;setDelegate&#8217;, prenant en argument unique l&#8217;instance du délégué.</div>
<div>Par exemple, pour définir un objet de type &#8216;Foo&#8217; comme délégué d&#8217;un objet NSWindow:</div>
<div class="macmade-code"><code class="macmade-source">Foo      * foo    = [ [ Foo alloc ] init ];<br />
</code> <code class="macmade-source"><span class="macmade-code-predefined">NSWindow</span> * window = [ [ <span class="macmade-code-predefined">NSWindow</span> alloc ] <span class="macmade-code-predefined">initWithContentRect</span>: <span class="macmade-code-predefined">NSMakeRect</span>( 0, 0, 100, 100 ) <span class="macmade-code-predefined">styleMask</span>: <span class="macmade-code-predefined">NSTitledWindowMask</span> <span class="macmade-code-predefined">backing</span>: <span class="macmade-code-predefined">NSBackingStoreBuffered</span> <span class="macmade-code-predefined">defer</span>: <span class="macmade-code-keyword">NO</span> ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">[ window <span class="macmade-code-predefined">setDelegate</span>: foo ];</code></div>
<div>Les deux premières lignes créent respectivement un objet de type &#8216;Foo&#8217; (défini dans notre application), et un objet de type &#8216;NSWindow&#8217; (du framework Cocoa).</div>
<div>La troisième ligne défini l&#8217;objet de type &#8216;Foo&#8217; comme délégué de notre objet &#8216;NSWindow&#8217;.</div>
<div>A partir de ce moment, à supposer que l&#8217;on ferme notre objet fenêtre:</div>
<div class="macmade-code"><code class="macmade-source">[ window close ];</code></div>
<div>L&#8217;objet délégué pourra être averti de cette opération, en implémentant tout simplement une méthode spécifique. Dans le cas précis, &#8216;windowWillClose&#8217;, dont voici le prototype:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )windowWillClose: ( <span class="macmade-code-predefined">NSNotification</span> * )notification;</code></div>
<div>Celle-ci permettra au délégué, juste avant la fermeture de la fenêtre, d&#8217;effectuer un certain nombre d&#8217;opérations, liées au bon fonctionnement de l&#8217;application.</div>
<h3>2. Comment fonctionne la délégation?</h3>
<div>Voyons maintenant comment l&#8217;objet &#8216;NSWIndow&#8217; implémente et utilise son objet délégué.</div>
<div>L&#8217;objet &#8216;NSWindow&#8217; contient bien sûr une variable d&#8217;instance de type &#8216;id&#8217;, représentant l&#8217;objet délégué, généralement nommée delegate, ainsi qu&#8217;une méthode permettant d&#8217;obtenir l&#8217;objet délégué, et une seconde permettant de le définir.</div>
<div>Autrement dit:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">@interface</span> <span class="macmade-code-predefined">NSWindow</span>: <span class="macmade-code-predefined">NSObject</span><br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@protected</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">id</span> <span class="macmade-code-ctag">delegate</span>;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )delegate;<br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )setDelegate: ( <span class="macmade-code-keyword">id</span> )object;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> <span class="macmade-code-predefined">NSWindow</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )delegate<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-ctag">delegate</span>;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )setDelegate: ( <span class="macmade-code-keyword">id</span> )object<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">delegate</span> = object;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>Ici, il est extrêmement important de préciser qu&#8217;un objet ne doit en aucun cas effectuer un &#8216;retain&#8217; sur son objet délégué, car cela aurait comme effet un &#8216;memory leak&#8217;, autrement dit une zone de mémoire allouée à notre application qui ne serait jamais libérée.</div>
<div>Il est également à noter qu&#8217;en Objective-C 2.0, l&#8217;utilisation d&#8217;une propriété peut être utilisée dans l&#8217;interface, pour permettre un accès aisé à l&#8217;objet délégué:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">@property</span>( <span class="macmade-code-keyword">nonatomic</span>, <span class="macmade-code-keyword">assign</span>, <span class="macmade-code-keyword">readwrite</span> ) <span class="macmade-code-ctag">delegate</span>;</code></div>
<div>A partir de là, les getter/setter peuvent également être automatiquement délcarés dans l&#8217;implémentation:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">@synthesize</span> delegate;</code></div>
<div>Si l&#8217;on reprend maintenant l&#8217;exemple de la méthode &#8216;close&#8217; de l&#8217;objet &#8216;NSWindow&#8217;:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )close<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-comment">// Do something...</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">delegate</span> <span class="macmade-code-predefined">respondsToSelector</span>: <span class="macmade-code-keyword">@selector</span>( windowWillClose ) ] ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">delegate</span> windowWillClose ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-comment">// Do something...</span><br />
</code> <code class="macmade-source">}</code></div>
<div>A un instant précis dans l&#8217;exécution de la méthode &#8216;close&#8217;, l&#8217;objet &#8216;NSWindow&#8217; se demande si son objet délégué possède une méthode nommée &#8216;windowWillClose&#8217;.<br />
Si c&#8217;est le cas, elle l&#8217;exécute, et poursuit sa propre exécution.</div>
<div>La méthode &#8216;close&#8217; n&#8217;a nullement besoin de vérifier si un objet délégué a été défini auparavant, étant donné qu&#8217;en Objective-C, envoyer un message (appeler une méthode) sur &#8216;nil&#8217; (un pointeur NULL sur un objet) est parfaitement valide.</div>
<div>L&#8217;objet délégué sera donc averti, à supposer qu&#8217;il implémente la méthode &#8216;windowWillClose&#8217;, de la fermeture de l&#8217;objet &#8216;NSWindow&#8217;.</div>
<h3>3. Délégation et notification</h3>
<div>Le framework Cocoa inclut également un système de notification, permettant là aussi à des objets d&#8217;être informé des stades d&#8217;exécution d&#8217;autres objets.</div>
<div>Dans notre exemple précédent, nous aurions donc aussi pu, pour être averti lors de la fermeture de la fenêtre, écrire le code suivant.</div>
<div class="macmade-code"><code class="macmade-source">[ [ <span class="macmade-code-predefined">NSNotificationCenter</span> defaultCenter ] <span class="macmade-code-predefined">addObserver</span>: foo <span class="macmade-code-predefined">selector</span>: <span class="macmade-code-keyword">@selector</span>( myObserverMethod: ) <span class="macmade-code-predefined">name:</span> <span class="macmade-code-predefined">NSWindowWillCloseNotification</span> <span class="macmade-code-predefined">object</span>: window ]:</code></div>
<div>Autrement dit, on déclare que la méthode &#8216;myObserverMethod&#8217; de l&#8217;objet de type &#8216;Foo&#8217; doit être lancée lors de l&#8217;événement &#8216;NSWindowWillCloseNotification&#8217; de la fenêtre. Dans ce cas, voici le prototype de la méthode &#8216;myObserverMethod&#8217;:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )myObserverMethod: ( <span class="macmade-code-predefined">NSNotification</span> * )notification;</code></div>
<div>On peut donc ici se demander pourquoi ces deux systèmes cohexistent.<br />
Ce qu&#8217;il faut bien comprendre, c&#8217;est que le système de notification permet uniquement d&#8217;être averti de certains événements, alors que le système de délégation permet en plus de modifier le comportement de l&#8217;objet concerné.</div>
<div>Prenons le cas de la méthode &#8216;windowShouldClose&#8217;, pouvant être implémentée dans le délégué d&#8217;un objet &#8216;NSWindow&#8217;, et dont voici le prototype:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">BOOL</span> )windowShouldClose: ( <span class="macmade-code-predefined">NSWindow</span> * )window;</code></div>
<div>On remarque que cette méthode retourne une valeur booléenne.</div>
<div>Si notre objet délégué implémente cette méthode, et qu&#8217;on lance la méthode &#8216;close&#8217; sur notre fenêtre, cette dernière ne se fermera effectivement que dans le cas où la méthode du délégué retourne la valeur &#8216;YES&#8217;. Dans le cas contraire, elle restera affichée sur l&#8217;écran.</div>
<div>Cela peut par exemple permettre de bloquer le processus de fermeture de la fenêtre, pour afficher un message d&#8217;alerte demandant à l&#8217;utilisateur s&#8217;il veut sauvegarder ses changements éventuels.</div>
<div>A ce moment là, c&#8217;est le délégué qui prend la responsabilité de savoir si et quand la fenêtre doit être fermée, ce qui serait évidemment impossible via le système de notification.</div>
<div>On voit donc ici bien la différence de logique entre la délégation et la notification, le premier pouvant agir sur l&#8217;objet concerné, au contraire du second.</div>
<div>Certains objets du framework Cocoa utilisent également leur délégué pour obtenir d&#8217;autre types d&#8217;informations, comme par exemple l&#8217;objet &#8216;NSBrowser&#8217; (la vue en colonne du Finder) qui utilise son délégué pour connaître les éléments à afficher.</div>
<h3>4. Chaîne de délégation</h3>
<div>A ce niveau là, on peut remarquer une certaine limitation dans le système de délégation. Un objet ne peut avoir qu&#8217;un seul et unique délégué.</div>
<div>Prenons le code suivant:</div>
<div class="macmade-code"><code class="macmade-source">[ window <span class="macmade-code-predefined">setDelegate</span>: foo ];<br />
</code> <code class="macmade-source">[ window <span class="macmade-code-predefined">setDelegate</span>: bar ];</code></div>
<div>Le délégué de l&#8217;objet &#8216;window&#8217; sera donc &#8216;bar&#8217;, qui remplacera &#8216;foo&#8217; à ce poste. L&#8217;objet &#8216;foo&#8217;, quand à lui, ne sera plus du tout en mesure de contrôler les différents aspects de la fenêtre.</div>
<div>Or il pourrait être fort utile, dans certains cas, de pouvoir placer plusieurs délégués sur un même objet. Nous allons donc implémenter un système permettant de chaîner les objet délégués.</div>
<h3>5. Implémentation &#8211; MultipleDelegateObject</h3>
<div>Nous allons tout d&#8217;abord créer un classe, qui servira de base aux classes voulant implémenter une chaîne de délégués:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-comment">/* MultipleDelegateObject.h */</span><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@interface</span> MultipleDelegateObject: <span class="macmade-code-predefined">NSObject</span><br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@protected</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">DelegateChain</span> * <span class="macmade-code-ctag">delegate</span>;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )addDelegate: ( <span class="macmade-code-keyword">id</span> )object;<br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )removeDelegate: ( <span class="macmade-code-keyword">id</span> )object;<br />
</code> <code class="macmade-source">- ( <span class="macmade-code-predefined"><span class="macmade-code-predefined">NSArray</span></span> * )delegates;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span>;</code></div>
<div>Nous n&#8217;allons pas gérer la chaîne de délégué dans cette objet, mais plutôt créer une seconde classe, nommée &#8216;DelegateChain&#8217;, que nous étudierons après.</div>
<div>Notre classe contient donc une méthode permettant d&#8217;ajouter un délégué, une méthode permettant d&#8217;en enlever un, et une méthode permettant d&#8217;obtenir sous forme de tableau tous les objets délégués.</div>
<div>L&#8217;implémentation est la suivante:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-comment">/* MultipleDelegateObject.m */</span><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@implementation</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )init<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( ( <span class="macmade-code-keyword">self</span> = [ <span class="macmade-code-keyword">super</span> init ] ) ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">delegate</span> = [ [ <span class="macmade-code-ctag">DelegateChain</span> alloc ] init ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-keyword">self</span>;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )dealloc<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">delegate</span> release ];<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-keyword">super</span> dealloc ];<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )addDelegate: ( <span class="macmade-code-keyword">id</span> )object<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">delegate</span> <span class="macmade-code-ctag">addDelegate</span>: object ];<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )removeDelegate: ( <span class="macmade-code-keyword">id</span> )object<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">delegate</span> <span class="macmade-code-ctag">removeDelegate</span>: object ];<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-predefined"><span class="macmade-code-predefined">NSArray</span></span> * )delegates<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> [ <span class="macmade-code-ctag">delegate</span> <span class="macmade-code-ctag">delegates</span> ];<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>La méthode &#8216;init&#8217; crée une nouvelle instance de la classe &#8216;DelegateChain&#8217;, et la stocke dans la variable d&#8217;instance &#8216;delegate&#8217;. La méthode &#8216;dealloc&#8217; libère cette resource lors de la destruction de l&#8217;objet.</div>
<div>Les trois autres méthodes ne font que re-router les appels sur l&#8217;objet de type &#8216;DelegateChain&#8217;, qui gérera elle les délégués multiples.</div>
<h3>6. Implémentation &#8211; DelegateChain</h3>
<div>Regardons maintenant l&#8217;interface de la classe &#8216;DelegateChain&#8217;:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-comment">/* DelegateChain.h */</span><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@interface</span> DelegateChain: <span class="macmade-code-predefined">NSObject</span><br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@protected</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">id</span> * <span class="macmade-code-ctag">delegates</span>;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> <span class="macmade-code-ctag">numberOfDelegates</span>;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> <span class="macmade-code-ctag">sizeOfDelegatesArray</span>;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSMutableDictionary</span> * <span class="macmade-code-ctag">hashs</span>;<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )addDelegate: ( <span class="macmade-code-keyword">id</span> )object;<br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )removeDelegate: ( <span class="macmade-code-keyword">id</span> )object;<br />
</code> <code class="macmade-source">- ( <span class="macmade-code-predefined">NSArray</span> * )delegates;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>Comme précisé auparavant, il ne faut pas effectuer de &#8216;retain&#8217; sur les objets délégués. Il nous est donc impossible d&#8217;utiliser un objet de type &#8216;NSMutableArray&#8217; ou &#8216;NSMutableDictionary&#8217; pour stocker les délégués, car ceci aurait pour effet un &#8216;retain&#8217; automatique lors de l&#8217;ajout.</div>
<div>Un tableau de pointeur sur les délégués (le type &#8216;id&#8217; est en fait un pointeur), alloué et ré-alloué si nécessaire avec les fonctions d&#8217;allocation de mémoire de la bibliothèque standard C, fera par contre très bien l&#8217;affaire. Il s&#8217;agit dans notre cas de la variable d&#8217;instance &#8216;delegates&#8217;.</div>
<div>Nous avons également une variable contenant le nombre de délégués actuellement affectés (&#8216;numberOfDelegates&#8217;), et une autre (&#8216;sizeOfDelegatesArray&#8217;) contenant la taille du tableau de pointeur précédemment cité, et dont nous verrons l&#8217;utilité plus tard.</div>
<div>La variable &#8216;hash&#8217;, quand à elle, servira à stocker les adresses mémoire des délégués, afin de trouver facilement leur position dans le tableau de pointeur.</div>
<div>Regardons maintenant, méthode par méthode, l&#8217;implémentation de la classe &#8216;DelegateChain&#8217;. En tout premier lieu, son initialisation:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">id</span> )init<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( ( <span class="macmade-code-keyword">self</span> = [ <span class="macmade-code-keyword">super</span> init ] ) ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> hash = [ [ <span class="macmade-code-predefined">NSMutableDictionary</span> <span class="macmade-code-predefined">dictionaryWithCapacity</span>: 10 ] retain ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( <span class="macmade-code-keyword">NULL</span> = ( <span class="macmade-code-ctag">delegates</span> = ( <span class="macmade-code-keyword">id</span> * )<span class="macmade-code-predefined">calloc</span>( 10, <span class="macmade-code-keyword">sizeof</span>( <span class="macmade-code-keyword">id</span> ) ) ) ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-comment">// Error management...</span><br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-keyword">self</span>;<br />
</code> <code class="macmade-source">}</code></div>
<div>Nous créons le dictionnaire qui nous permettra de stocker les adresses mémoire, et nous réservons une zone dans la mémoire pour stocker les pointeurs vers nos objets délégués. Nous réservons une zone pouvant contenir 10 objets, afin d&#8217;éviter d&#8217;avoir à appeler les fonctions d&#8217;allocation à chaque fois qu&#8217;un délégué est ajouté, ce qui nuirait aux performances. En cas de dépassement, nous ré-allouerons cette zone par 10.</div>
<div>Comme nous avons réservé de la mémoire, il ne faut pas oublier de la libérer lors de la destruction de l&#8217;objet:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )dealloc<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">free</span>( <span class="macmade-code-ctag">delegates</span> );<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">hashs</span> release ];<br />
</code> <code class="macmade-source"> [ <span class="macmade-code-keyword">super</span> dealloc ];<br />
</code> <code class="macmade-source">}</code></div>
<div>Regardons maintenant la méthode utilisée pour ajouter un délégué:</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )addDelegate: ( <span class="macmade-code-keyword">id</span> )object<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSString</span> * hash;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( object == <span class="macmade-code-keyword">nil</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span>;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( <span class="macmade-code-ctag">numberOfDelegates</span> == <span class="macmade-code-ctag">sizeOfDelegatesArray</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( <span class="macmade-code-keyword">NULL</span> == ( <span class="macmade-code-ctag">delegates</span> = ( <span class="macmade-code-keyword">id</span> * )<span class="macmade-code-predefined">realloc</span>( <span class="macmade-code-ctag">delegates</span>, ( <span class="macmade-code-ctag">sizeOfDelegatesArray</span> + 10 ) * <span class="macmade-code-keyword">sizeof</span>( <span class="macmade-code-keyword">id</span> ) ) ) ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-comment">// Error management...</span><br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">sizeOfDelegatesArray</span> += 10;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> hash = [ [ <span class="macmade-code-predefined">NSNumber</span> <span class="macmade-code-predefined">numberWithUnsignedInteger</span>: ( <span class="macmade-code-predefined">NSUInteger</span> )object ] stringValue ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">hashs</span> <span class="macmade-code-predefined">objectForKey</span>: hash ] != <span class="macmade-code-keyword">nil</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span>;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">delegates</span>[ <span class="macmade-code-ctag">numberOfDelegates</span> ] = object;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> [ <span class="macmade-code-ctag">hashs</span> <span class="macmade-code-predefined">setObject</span>: [ <span class="macmade-code-predefined">NSNumber</span> <span class="macmade-code-predefined">numberWithUnsignedInteger</span>: <span class="macmade-code-ctag">numberOfDelegates</span> ] <span class="macmade-code-predefined">forKey</span>: hash ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">numberOfDelegates</span>++;<br />
</code> <code class="macmade-source">}</code></div>
<div>Nous avons précédemment alloué un emplacement pour 10 délégués. A supposer qu&#8217;il y en ait 10, et que nous ajoutons un onzième, nous augmentons la zone mémoire de 10, grâce à la fonction &#8216;realloc&#8217;.</div>
<div>Nous prenons ensuite l&#8217;adresse mémoire de l&#8217;objet, sous forme de chaîne de charactère, et nous contrôlons que l&#8217;objet n&#8217;a pas déjà ajouté comme délégué. De cette façon, il est impossible d&#8217;ajouter plusieurs fois le même objet comme délégué.</div>
<div>Il ne nous reste plus qu&#8217;à stocker le pointeur vers notre objet, son adresse mémoire avec sa position dans le tableau de pointeur, et augmenter de 1 la variable contenant le nombre de délégués.</div>
<div>Sur le même principe, voici la fonction permettant d&#8217;enlever un délégué.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )removeDelegate: ( <span class="macmade-code-keyword">id</span> )object<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSString</span> * hash;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> index;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> i;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( object == <span class="macmade-code-keyword">nil</span> || <span class="macmade-code-ctag">numberOfDelegates</span> == 0 ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span>;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> hash = [ [ <span class="macmade-code-predefined">NSNumber</span> <span class="macmade-code-predefined">numberWithUnsignedInteger</span>: ( <span class="macmade-code-predefined">NSUInteger</span> )object ] stringValue ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">hashs</span> <span class="macmade-code-predefined">objectForKey</span>: hash ] == <span class="macmade-code-keyword">nil</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span>;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> index = [ [ <span class="macmade-ctag">hashs</span> <span class="macmade-code-predefined">objectForKey</span>: hash ] unsignedIntegerValue ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">for</span>( i = index; i &lt; <span class="macmade-code-ctag">numberOfDelegates</span> - 1; i++ ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">delegates</span>[ i ] = <span class="macmade-code-ctag">delegates</span>[ i + 1 ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> [ hash <span class="macmade-code-predefined">removeObjectForKey</span>: hash ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-ctag">numberOfDelegates</span>--;<br />
</code> <code class="macmade-source">}</code></div>
<div>Le fonctionnement de cette méthode repose sur le même principe que la précédente, avec une petite subtilité.</div>
<div>A supposer que l&#8217;on aie 5 délégués, et que l&#8217;on enlève l&#8217;objet se trouvant en position 3 dans notre tableau de pointeur, nous aurons un trou. Pour éviter cela, nous décalons donc également tous les pointeurs se trouvant après celui que nous avons ôté.</div>
<div>Et en dernier lieu, la méthode permettant d&#8217;obtenir un tableau contenant tous les objets délégués.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-predefined">NSArray</span> * )delegates<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> i;<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSMutableArray</span> * delegatesArray;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( <span class="macmade-code-ctag">numberOfDelegates</span> == 0 ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> [ <span class="macmade-code-predefined">NSArray</span> array ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> delegatesArray = [ <span class="macmade-code-predefined">NSMutableArray</span> <span class="macmade-code-predefined">arrayWithCapacity</span>: <span class="macmade-code-ctag">numberOfDelegates</span> ];<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">for</span>( i = 0; i &lt; <span class="macmade-code-ctag">numberOfDelegates</span>; i++ ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> [ delegatesArray <span class="macmade-code-predefined">addObject</span>: <span class="macmade-code-ctag">delegates</span>[ i ] ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> [ <span class="macmade-code-predefined">NSArray</span> <span class="macmade-code-predefined">arrayWithArray</span>: delegatesArray ];<br />
</code> <code class="macmade-source">}<br />
</code></div>
<div>Il s&#8217;agit d&#8217;une simple boucle sur notre tableau de pointeur, qui ajoute les objets pointés dans un objet de type &#8216;NSArray&#8217;.</div>
<h3>7. Runtime et re-routage des méthodes</h3>
<div>Nous avons vu plus haut que, pour déterminer si le délégué possède une certaine méthode, il fallait utiliser la méthode &#8216;respondsToSelector&#8217; sur l&#8217;objet délégué.</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">delegate</span> <span class="macmade-code-predefined">respondsToSelector</span>: <span class="macmade-code-keyword">@selector</span>( someMethod ) ] ) {}</code></div>
<div>Pour éviter de changer les habitudes de programmation des dévelopeurs Cocoa, nous allons rendre ceci possible sur notre objet &#8216;DelegateChain&#8217;.</div>
<div>Actuellement. le code ci-dessus n&#8217;a aucune chance de fonctionner, vu que notre objet &#8216;DelegateChain&#8217;, qui contient les délégués, ne possède bien sûr pas leurs méthodes à son étage.</div>
<div>Nous pouvons par contre parfaitement surcharger (re-déclarer) dans notre classe la méthode &#8216;respondToSelector&#8217; (à l&#8217;origine, elle est déclarée dans la classe &#8216;NSObject&#8217;), pour lui affecter un comportement autre que celui par défaut.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">BOOL</span> )<span class="macmade-code-predefined">respondsToSelector</span>: ( <span class="macmade-code-keyword">SEL</span> )selector<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> i;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">for</span>( i = 0; i &lt; <span class="macmade-code-ctag">numberOfDelegates</span>; i++ ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">delegates</span>[ i ] <span class="macmade-code-predefined">respondsToSelector</span>: selector ] == <span class="macmade-code-keyword">YES</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-keyword">YES</span>;<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-keyword">NO</span>;<br />
</code> <code class="macmade-source">}<br />
</code></div>
<div>Nous effectuons donc une boucle sur notre tableau de pointeur, et contrôlons si l&#8217;un des délégué possède la méthode demandée. De cette manière, nous pouvons utiliser notre objet &#8216;DelegateChain&#8217; comme s&#8217;il s&#8217;agissait d&#8217;un délégué normal et unique.</div>
<div>Pour que cela fonctionne, il nous faut également surcharger la méthode &#8216;methodSignatureForSelector&#8217; (NSObject). Celle-ci permet à l&#8217;environnement runtime d&#8217;Objective-C d&#8217;obtenir les infos nécessaires sur une méthode particulière, comme son type de retour, ses arguments, etc.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-predefined">NSMethodSignature</span> * )methodSignatureForSelector: ( <span class="macmade-code-keyword">SEL</span> )selector<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> i;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">for</span>( i = 0; i &lt; <span class="macmade-code-ctag">numberOfDelegates</span>; i++ ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">delegates</span>[ i ] <span class="macmade-code-predefined">respondsToSelector</span>: selector ] == <span class="macmade-code-keyword">YES</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> [ [ <span class="macmade-code-ctag">delegates</span>[ i ] class ] <span class="macmade-code-predefined">instanceMethodSignatureForSelector</span>: selector ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">return</span> <span class="macmade-code-keyword">nil</span>;<br />
</code> <code class="macmade-source">}</code></div>
<div>Désormais, nous pouvons savoir si au moins un délégué possède une méthode spécifique. Mais comment appeler le ou les délégués contenant cette méthode?</div>
<div>Ici aussi, nous allons garder le même système d&#8217;appel que pour un délégué unique, à savoir que la méthode désirée sera appelée directement sur notre objet &#8216;DelegateChain&#8217;, qui devra se charger de re-router cet appel vers le ou les délégués concernés.</div>
<div>Pour ce faire, nous allons implémenter la méthode &#8216;forwardInvocation&#8217; dans notre classe.</div>
<div>Cette dernière est automatiquement appelée par l&#8217;environnement runtime d&#8217;Objective-C lorsqu&#8217;une méthode est appelée sur un objet  ne la possédant pas. Ceci afin de donner une dernière chance à l&#8217;objet en question de gérer l&#8217;erreur.</div>
<div>Le même genre de concept est utilisé dans de nombreux langages de programmation objet. On peut par exemple citer les méthodes virtuelles de C++ ou encore la méthode &#8216;__call&#8217; en PHP5.</div>
<div class="macmade-code"><code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )forwardInvocation: ( NSInvocation * )invocation<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSUInteger</span> i;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">for</span>( i = 0; i &lt; <span class="macmade-code-ctag">numberOfDelegates</span>; i++ ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> <span class="macmade-code-keyword">if</span>( [ <span class="macmade-code-ctag">delegates</span>[ i ] <span class="macmade-code-predefined">respondsToSelector</span>: [ invocation selector ] ] == <span class="macmade-code-keyword">YES</span> ) {<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"> [ invocation <span class="macmade-code-predefined">invokeWithTarget</span>: <span class="macmade-code-ctag">delegates</span>[ i ] ];<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source"> }<br />
</code> <code class="macmade-source">}</code></div>
<div>Le système de délégation multiple est ici complétement opérationnel. Pour en bénéficier dans une classe, il suffit désormais que cette dernière soit une sous-classe de &#8216;MultipleDelegateObject&#8217;. Aucune autre implémentation n&#8217;est nécessaire.</div>
<h3>8. Conclusion</h3>
<div>Un tel système permet de définir des classes ayant un nombre infini de délégués. Par contre, les objets intrinsèques du framework Cocoa, tels &#8216;NSWindow&#8217;, ne pourront pas bénéficier de ce système.</div>
<div>Il est par contre parfaitement envisageable d&#8217;implémenter ce système de délégation multiple sur des objets comme &#8216;NSWindow&#8217;.</div>
<div>Le language Objective-C permet en effet la définition de catégories, permettant d&#8217;ajouter des méthodes dans n&#8217;importe quel objet disponible, que celui-ci soit défini dans notre projet, ou qu&#8217;il fasse partie d&#8217;un framework du système. Par exemple:</div>
<div class="macmade-code"><code class="macmade-source"><span class="macmade-code-keyword">@interface</span> <span class="macmade-code-predefined">NSObject</span>( MyCategory )<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )sayHello;<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span><br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@implementation</span> <span class="macmade-code-predefined">NSObject</span>( MyCategory )<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source">- ( <span class="macmade-code-keyword">void</span> )sayHello<br />
</code> <code class="macmade-source">{<br />
</code> <code class="macmade-source"> <span class="macmade-code-predefined">NSLog</span>( <span class="macmade-code-string">@"Hello world!"</span> );<br />
</code> <code class="macmade-source">}<br />
</code> <code class="macmade-source"><br />
</code> <code class="macmade-source"><span class="macmade-code-keyword">@end</span></code></div>
<div>Le code ci-dessus ajoute une méthode &#8216;sayHello&#8217; dans la classe &#8216;NSObject&#8217;, faisant partie du framework Cocoa. Comme &#8216;NSObject&#8217; est la classe de base pour toutes les classes Objective-C, toutes les classes disponibles possèdent maintenant une méthode &#8216;sayHello&#8217;.</div>
<div>Nous pourrions donc parfaitement ajouter les méthodes &#8216;addDelegate&#8217;, &#8216;removeDelegate&#8217; et &#8216;delegates&#8217; à l&#8217;objet &#8216;NSWindow&#8217;.</div>
<div>La seule limitation des catégories est qu&#8217;il est impossible d&#8217;ajouter des variables d&#8217;instance à une classe. Par contre, l&#8217;objet &#8216;NSWindow&#8217; possède déjà une variable d&#8217;instance prévue pour le délégué. Il faudra simplement ne pas oublier de redéfinir la méthode &#8216;setDelegate&#8217; de &#8216;NSWindow&#8217; dans notre catégorie. L&#8217;utilisation d&#8217;une variable globale statique (donc dont l&#8217;accès est limité au fichier qui l&#8217;a déclarée) est également une possibilité envisageable pour stocker les chaînes de délégués.</div>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.netinfluence.com/2009/08/24/implementation-d-un-systeme-de-delegation-multiple-en-objective-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

