Author Archives: Alexis Kinsella

Author Archives: Alexis Kinsella

Transformez vos callbacks Node.js en promises Q

Transformez vos callbacks Node.js en promises Q

Le callback Hell en JavaScript, on en a tous entendu parler, voir même un peu trop, mais pas sans raison.

De bonnes règles de codage permettent tout de même de gommer en grande partie ce problème, et l’usage des promises est à mettre en tête de liste des bonnes pratiques pour y parvenir.

Nous allons voir dans cet article différentes techniques proposées par le module Q permettant passer d’une écriture de code à base de callback à une écriture à base de promises.

Un exemple de départ

Partons de l’extrait suivant qui permet d’importer des données de conférences:

En JavaScript:

var importConferences = function(conferences, callback) {
  return conferenceImporter.importData(conferences, function(err, result) {
    if (err) {
      return callback(err);
    } else {
      return doSomethingWithResult(result, function(err, otherResult) {
        return callback(err, otherResult);
      });
    }
  });
};

Puis en CoffeeScript:

importConferences = (conferences, callback) ->
    conferenceImporter.importData conferences, (err, result) ->
        if err
            callback(err)
        else
            doSomethingWithResult result, (err, otherResult) ->
                callback(err, otherResult)

L’usage de CoffeeScript permet déjà de gommer une partie l’effet pyramide des appels de fonctions. Néanmoins, ce n’est pas suffisant, et dans le cas où de nombreux appels sont imbriqués, on s’y perd rapidement dans la compréhension du programme.

Q.defer()

Avec l’usage de la fonction defer() de Q, il sera possible de réécrire le même code de la façon suivante:

importConferences = (conferences) ->
    deferred = Q.defer()
    conferenceImporter.importData conferences, (err, result) ->
        doSomethingWithResult result, (err, result) ->
            if err
                deferred.reject(err)
            else
                deferred.resolve(result)
    deferred.promise

C’est un peu plus verbeux, mais la transformation du callback initial en promise permet maintenant d’appeler la fonction importConferences de la façon suivante:

importConferences(conferences)
.then (result) ->
    console.log "Result: #{util.inspect(result)}"
    someOtherPromise()
.then (otherResult)
    console.log "Result: #{util.inspect(otherResult)}"
.fail (err) ->
    console.log "Error - Message: #{err.message}"

En appliquant également la fonction defer() pour réécrire les fonctions importData et doSomethingWithResult, nous obtenons le code suivant:

importConferences = (conferences) ->
    conferenceImporter.importData(conferences)
    .then (result) ->
        doSomethingWithResult(result)

Plus besoin de la fonction defer() puisque nous travaillons avec des fonctions retournant des promises.

La fonction fail() n’est pas utilisée ici, car nous laissons le soin à la fonction appelante d’ajouter la gestion des erreurs à la promise retournée.

deferred.makeNodeResolver()

Dans certains contextes, vous ne pouvez pas vous baser sur une promise retournée par un appel de fonction. C’est par exemple le cas lorsque vous appelez une fonction d’un module qui ne supporte pas les promises.

Pour éviter d’écrire une résolution manuelle de promise basée sur le résultat d’un callback, Q propose la fonction makeNodeResolver. Elle simplifie l’écriture de conversion comme suit:

importConferences = (conferences) ->
    deferred = Q.defer()
    conferenceImporter.importData conferences, (err, result) ->
        doSomethingWithResult result, deferred.makeNodeResolver()
    deferred.promise

Le code n’est finalement pas plus verbeux que l’original, et vous permet de travailler avec des promises plutôt que des callbacks.

Conclusion

Les techniques de conversion visant à remplacer l’usage de callback par des promises sont variées et permettent en général de s’adapter au besoin.

Liens utiles

Pour en savoir plus sur la librairie Q, vous pouvez visiter la page du projet sur GitHub à l’adresse suivante:

https://github.com/kriskowal/q

Mongoose, les promises et Q

Mongoose, les promises et Q

Q est un module de promises pour Node.js qui implémente le standard Promises/A+. Il est devenu peu à peu l’implémentation de référence, et de nombreux tutoriaux en présentent différentes fonctionnalités.

De même, Mongoose est le module de facto à utiliser lorsqu’on intègre la base MongoDB dans un projet Node.js, puisqu’il est supporté officiellement par MongoDB, Inc.

Depuis quelques temps maintenant, le module Mongoose propose le support des promises en plus de son fonctionnement via callback via l’appel de la fonction exec. C’est à dire, qu’il est possible d’écrire:

Conference.findOne({ id: 12 }).exec()
.then (conference) ->
    console.log conference
    next()
, (err) ->
    # handle error here.

Malheureusement, l’implémentation des promises utilisées par Mongoose n’est pas compatible avec l’implémentation Q. Notamment, il n’est pas possible d’utiliser la fonction fail, et d’écrire le code précédent de la façon suivante:

Conference.findOne({ id: 12 }).exec()
.then (conference) ->
    console.log conference
    next()
.fail (err) ->
    # handle error here.

La promise renvoyée par Mongoose n’est donc pas directement intégrable avec les promises Q. On peut donc penser qu’il est compliqué d’intégrer les deux types de promises.

Heureusement Q propose une solution simple pour les intégrer avec la fonction Q() qui permet de wrapper une promise Mongoose dans une promise Q, et donc d’intégrer les promises Mongoose dans des chaînages de promises Q, ou bien d’utiliser tout simplement les syntaxes Q.

Ainsi, vous devrez écrire le code suivant:

Q(Conference.findOne({ id: 12 }).exec())
.then (conference) ->
    console.log conference
    next()
.fail (err) ->
    # handle error here.

De façon plus globale, si vous travaillez avec une autre librairie de promises que Q, vous pouvez wrapper vos promises avec la fonction Q() dans la mesure où votre librairie propose une syntaxe compatible avec les wrappers Q. Dixit la doc de la librairie:

Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more

Pour aller plus loin

La homepage GitHub de la librairie Q et sa documentation:

https://github.com/kriskowal/q

Logger le contenu de vos objets avec Node.js

Logger le contenu de vos objets avec Node.js

Le contenu des logs est un élément essentiel de votre programme, bien souvent laissé de côté, il peut s’avérer précieux en cas problème.

En particulier, il arrive de vouloir logger le contenu d’un objet ou bien une de ses propriétés. Bien souvent, le premier réflexe sera d’en afficher le contenu en concaténant son contenu dans une chaine de caractère comme suit:

foobar = foo: "bar"
console.log "Contenu de la variable foobar: '#{foobar}'"

Malheureusement, le résultat ne correspond pas toujours à ce qu’on imagine:

Contenu de la variable foobar: '[object Object]'

Vu comme ça, on n’en fera pas grand chose si on met le nez dans les logs. Bien sûr, il est possible d’afficher la valeur de la propriété ‘foobar’ de l’objet:

console.log "Contenu de la variable foobar: '#{foobar.foo}'"

Le résultat sera un peu meilleur car on sera en mesure de logger la valeur de foo:

Contenu de la variable foobar: 'bar'

Dans notre cas, nous avons de la chance, car la variable ‘foo’ est de type String. Mais si la variable en question est un objet ou bien un tableau, nous tomberons sur le même problème.

JavaScript et Node.js nous proposent au moins deux solutions pour nous aider à produire un log convenable: La fonction ‘JSON.stringify’, et la fonction ‘inspect’ du module ‘util’.

JSON.stringify()

Bien connu dans le mode du JavaScript côté browser pour sérialiser le contenu d’une requête AJAX par exemple, on ne pense pas toujours à utiliser cette méthode pour sérialiser un objet ou bien un tableau JavaScript dans le but d’en logger son contenu:

console.log "Contenu de la variable foobar: '#{JSON.stringify(foobar})'"

On obtient déjà quelque chose de bien plus intéressant, c’est à dire un log avec un descriptif complet de l’objet au format JSON:

Contenu de la variable foobar: '{"foo":"bar"}'

Des objets plus complexes peuvent néanmoins devenir difficile à relire dans les logs, il ne faut donc pas hésiter à renseigner les informations de formatage du JSON lors de l’appel de la méthode ‘stringify’, qui permettent d’obtenir un log plus lisible avec un contenu bien indenté:

console.log "Contenu de la variable foobar: '#{JSON.stringify(foobar, undefined, 2})'"

ce qui donne:

Contenu de la variable foobar: '{
  "foo": "bar"
}'

Le dernier paramètre permet de spécifier l’indentation souhaitée.

La documentation complète de la méthode stringify peut être consulté sur le site de Mozilla: https://developer.mozilla.org/fr/docs/JavaScript/Reference/Objets_globaux/JSON/stringify

La méthode JSON.stringify peut être utilisée également avec des tableaux:

foo = [ "foo", "bar" ]
console.log "Contenu de la variable foobar: '#{JSON.stringify(foo, undefined, 2)}'"

ce qui donne:

Contenu de la variable foobar: '[
  "foo",
  "bar"
]'

Malheureusement, cela ne fonctionne pas avec les fonctions qui ne font pas partie du standard JSON:

bar = (foo, bar) -> "#{foo}-#{bar}"
console.log "Contenu de la variable foobar: '#{JSON.stringify(bar, undefined, 2)}'"

ce qui donne:

Contenu de la variable foobar: 'undefined'

Il ne faut pas oublier que nous détournons une fonctionnalité qui n’est pas spécialement faite pour le log au départ… Heureusement notre bonne vieille méthode toString() appelée sur la fonction nous sortira d’affaire:

console.log "Contenu de la variable foobar: '#{bar.toString()}'"

ou tout simplement:

console.log "Contenu de la variable foobar: '#{bar}'"

donne:

Contenu de la variable foobar: 'function (foo, bar) {
    return "" + foo + "-" + bar;
  }

util.inspect()

Le module util de Node.js fournit quelques fonctions intéressantes, dont la fonction: inspect. Elle permet de formatter un contenu de la façon que le réalise la fonction JSON.stringify que ce soit un objet ou bien un tableau. Elle a l’avantage d’être plus souple en proposant différentes options de sérialisation telles qu’une profondeur limite d’inspection ou bien encore la capacité d’appeler la méthode inspect() sur les sous-objets de l’arbre, lorsqu’ils la propose, afin de produire un contenu sérialisé spécifique.

Par exemple, les appels suivants:

util = require 'util'

console.log "Contenu de la variable foobar: '#{util.inspect(foobar)}'"
console.log "Contenu de la variable foobar: '#{util.inspect(foo)}'"
console.log "Contenu de la variable foobar: '#{util.inspect(bar)}'"

donneront:

Contenu de la variable foobar: '{ foo: 'bar' }'
Contenu de la variable foobar: '[ 'foo', 'bar' ]'
Contenu de la variable foobar: '[Function]'

Et la customisation de la sérialisation comme suit:

qix = { foo:"bar", foobar: { inspect: () -> "Some custom representation of foobar" } }
console.log "Contenu de la variable foobar: '#{util.inspect(qix)}'"

donnera:

Contenu de la variable foobar: '{ foo: 'bar', foobar: Some custom representation of foobar }'

On notera avec ce dernier exemple que la fonction util.inspect() n’a pas vocation à produire un JSON valide, mais elle produira par défaut une notation proche du JSON.

Il est possible entre autre d’afficher les propriétés non-enumerables d’un objet, de coloriser le résultat de l’appel ou bien encore de désactiver l’appel des inspections customisées sur les objets.

Pour approfondir: http://nodejs.org/api/util.html#util_util_inspect_object_options

Pour aller plus loin …

Sachez qu’il existe des modules Node.js dédiés à la sérialisation d’objets à des fins d’analyse. Par exemple, le module nodedump permet de logger dans une sortie HTML un tableau qui détaille le contenu de l’objet:

nodedump

Bien entendu, vous pourrez toujours préférer le debugger de votre IDE favori, son côté interactif apporte de nombreux bénéfices, et l’évaluation d’expressions se révèle être d’une grande aide:

debugger

Sortie de l’application mobile Xebia pour iPhone et iPad

Sortie de l’application mobile Xebia pour iPhone et iPad

appli-XebiaC’est avec une joie non dissimulée que je vous annonce aujourd’hui la sortie de l’application Xebia pour iPhone et iPad. Publiée il y a tout juste quelques jours sur l’App Store, l’application vous propose de réunir au sein d’une seule et unique interface l’ensemble des flux d’informations de Xebia, ainsi que des bonus agiles qui viendront s’étoffer avec le temps.

L’application est optimisée pour iOS 7, mais fonctionne parfaitement sur iOS 6.

Où trouver l’application ?

Vous pouvez retrouver l’application mobile Xebia sur son mini-site dédié à l’adresse suivante: http://xebia-app.com, ou bien directement sur l’App Store.

Les fonctionnalités

Au menu des réjouissances :

  • L’application Xebia vous permettra de consulter l’ensemble des articles du blog dans un format spécialement adapté aux mobiles et tablettes Apple. En particulier, la mise en page des articles prend en charge la mise en forme des codes sources afin de rendre la lecture plus agréable.
  • Vous pourrez également retrouver les articles du blog Xebia grâce à leur tag ou encore leur catégorie. 
  • Si vous n’êtes pas un aficionados de Twitter ou déjà abonné à notre timeline, vous pourrez tout de même suivre les tweets de Xebia en consultant les dernières infos en un clin d’oeil sur un écran dédié.
  • En bon craftsman et agiliste convaincu, vous pourrez retrouver l’ensemble du deck de cartes Xebia Essentials, et éplucher leurs conseils avisés ! 
  • Par ailleurs, il sera possible de consulter les dates des prochains Tech Events et de visionner ceux déjà passés si vous les avez manqués. 
  • Enfin, si vous souhaitez être informé en premier de la sortie d’un nouvel article ou bien encore du dernier Tech-Event, sachez que vous pourrez être notifié en push à peine quelques instants après publication !

Du côté de la technique

Côté client

L’application Xebia est une appli native basée sur une stack Open-Source (AFNetworking, DTCoreText, MBProgressHUD, ParseKit, ShareKit, PKRevealController, SDWebImage, SVPullToRefresh, TTTAttributedLabel, et bien d’autres…).

Elle est construite dans le Cloud grâce à Travis-CI, et est disponible en Open-Source sur GitHub.

Côté tooling, elle s’appuie sur XCTool, l’outil de build de Facebook, ainsi que CocoaPods pour la partie gestion de dépendances.

Côté serveur

L’application mobile Xebia s’appuie sur un backend Node.js qui sert l’ensemble des informations via une API REST spécialement développée pour les besoins de l’application. Les différents flux d’informations sont synchronisés régulièrement dans le but de les stocker en cache et de les resservir dans un format adapté, avec des performances optimales. C’est par ailleurs ce même backend qui a la charge de servir les notifications de l’application mobile via l’APNS d’Apple.

Le fruit du travail sur le backend Node.js est disponible sous forme d’une présentation couverte lors de l’Open-XKE que vous pouvez retrouver à l’adresse suivante: http://akinsella.github.io/node-overview/

Quid d’une application mobile Xebia pour Android ? 

L’application mobile Xebia pour iPhone et iPad a été développée par mes soins dans sa première version dans le but de partager la passion de Xebians. Sachez qu’il n’existe pas actuellement d’équivalent à cette application pour Android, mais vous pouvez d’ores et déjà retrouver l’application Xebia Essentials de Gautier Mechling (Nilhcem) sur le Play Store de Google.

Feedback

Bien entendu, tout feedback est le bienvenu. N’hésitez pas à partager vos idées d’améliorations, anomalies rencontrées ou bien encore les fonctionnalités que vous attendez !

UITableView + API GitHub + CocoaPods = Keep it Simple, keep it Stupid!

UITableView + API GitHub + CocoaPods = Keep it Simple, keep it Stupid!

Nous avons vu dans un article précédent comment utiliser RestKit pour se faciliter la vie lorsque nous travaillons avec des services web exploitant le format JSON. Toutefois, l’utilisation d’un framework fullstack peut se révéler contraignant dès lors que l’on sort du cadre pour lequel il a été destiné. Malheureusement, cela arrive souvent assez rapidement.

Nous verrons dans cet article comment reproduire une application similaire à celle construite grâce à RestKit, sans pour autant abandonner l’idée de gagner du temps grâce à l’utilisation de quelques librairies bien choisies :

Le monde iOS, comme tout environnement mature, dispose de nombreuses librairies Open Source intégrables dans vos projets via l’utilisation d’un Dependency Manager. Dans notre cas, nous utiliserons CocoaPods déjà présenté dans un article précédent.

La création de ce tutoriel fait suite à une présentation en XKE d’une session d’1h30 d’introduction aux développements iOS. Ce tutoriel est donc réalisable en un temps raisonnable en suivant les instructions ci-dessous.

Création du projet

Avant d’utiliser CocoaPods, vous devrez créer un projet de type Empty Application pour iOS via XCode:

Vous aurez ensuite à créer un fichier Podfile à la racine de votre projet XCode avec les dépendances suivantes:

platform :ios, '5.0'
pod 'JSONKit', '1.5pre'
pod 'Underscore.m', '0.2.0'
pod 'AFNetworking', '1.1'
pod 'MBProgressHUD', '0.6'
pod 'SVPullToRefresh', '0.4'
pod 'SDURLCache', '1.2'
pod 'AFHTTPRequestOperationLogger', '0.10.0'
pod 'DCKeyValueObjectMapping', '1.3'

Puis, vous devrez exécuter la commande suivante pour générer le workspace et intégrer le code des dépendances:

pod install

Il faudra alors relancer votre projet en ouvrant le fichier *.XCodeWorkspace, plutôt que le fichier *.XCodeProject. Vous serez alors prêt à développer votre application.

(suite…)

Intégration de RestKit avec une UITableView

Intégration de RestKit avec une UITableView

Nous avons découvert dans un précédent article comment utiliser RestKit pour récupérer des structures de données JSON depuis une ressource HTTP et les mapper sur un modèle métier. Nous allons voir dans ce nouvel article comment adapter le code existant pour afficher les résultats dans une UITableView iOS. Pour cela, nous allons continuer à travailler avec les APIs GitHub, et nous fixer pour objectif d’afficher les utilisateurs d’une organisation.

Notes: 

  • La version actuelle de RestKit est la 0.20. Cet article met en oeuvre la version 0.10.

Installation

Dans un premier temps, nous allons créer un projet adapté pour iOS via Xcode. Vous devrez sélectionner dans l’assistant de création de projet une application pour iOS avec un template de type Empty Application.

Capture-d’écran-2012-10-28-à-09.27.53.png

Dans un second temps, nous allons cibler dans notre fichier de Podfile la plateforme iOS, puis ajouter une dépendance appelée SDWebImage qui sera présentée plus tard:

platform :ios

pod 'JSONKit',                          '1.5pre'
pod 'LibComponentLogging-Core',         '1.2.2'
pod 'LibComponentLogging-NSLog',        '1.0.4'
pod 'Reachability',                     '3.0.0'
pod 'RestKit',                          '0.10.1'
pod 'Underscore.m',                     '0.1.0'
pod 'SDWebImage',                       '2.6'

Les autres dépendances ont été ajoutées lors de notre précédent article. Pour plus d’informations sur l’utlisation de CocoaPods, c’est par ici

Description de l’API GitHub

En complément de l’accès au listing des repositories d’une organisation, nous allons utiliser une seconde ressource de l’API GitHub qui permet de lister les utilisateurs d’une organisation. L’URL est la suivante:

https://api.github.com/orgs/:organization/public_members

(suite…)

Introduction à RestKit

Introduction à RestKit

Lorsque vous développez une application iOS ou bien OS X travaillant avec des flux de données JSON, vous pouvez décider de vous contenter d’utiliser ce que les SDK d’Apple proposent ou bien vous pouvez vous reposer sur des librairies qui vous facilitent le travail.

Si vous optez pour la première solution, le travail à accomplir peut se révéler complexe et fastidieux. Mieux vaut s’appuyer sur des librairies reconnues pour leur qualités telles qu’AFNetworking pour la gestion des appels HTTP ou bien encore JSONKit pour la sérialisation & désérialisation de payloads JSON.

En utilisant ces librairies vous pourrez mettre de côté une partie de la complexité, il vous restera tout de même à gérer une stratégie de mise en cache des données et vous devrez mapper les payloads JSON avec une représentation objet.

Toutefois, si vous ne souhaitez pas gérer ces problèmes à la main, il vous reste la possibilité d’utiliser la librairie RestKit qui propose:

  • La consommation de données JSON depuis un serveur distant
  • Le mapping entre les structures de données JSON et les objets de votre modèle de données
  • Le stockage en cache de requêtes effectuées
  • Le stockage en base de votre modèle métier via l’utilisation de CoreData
  • L’initialisation de votre base de données

Initialisation du projet

Si vous souhaitez manipuler le code source fourni dans cet article, vous devrez utiliser CocoaPods que nous avons découvert dans un article précédent.

Avant d’utiliser CocoaPods, vous devrez créer un projet en ligne de commande pour OS X via Xcode:

xcode

Ensuite, vous aurez à créer un fichier Podfile à la racine de votre projet Xcode avec les dépendances suivantes:

platform :osx
pod 'JSONKit',                      '1.5pre'
pod 'LibComponentLogging-Core',     '1.2.2'
pod 'LibComponentLogging-NSLog',    '1.0.4'
pod 'Reachability',                 '3.0.0'
pod 'RestKit',                      '0.10.1'
pod 'Underscore.m',                 '0.1.0'

Puis, vous devrez exécutez la commande suivante:

pod install

Il faudra alors relancer votre projet en ouvrant le fichier *.XCodeWorkspace, plutôt que le fichier *.XCodeProject. Vous serez alors prêt à tester RestKit.

(suite…)

Programmation fonctionnelle en Objective-C

Programmation fonctionnelle en Objective-C

underscoremDans un article précédent, nous avons entrevu les possibilités offertes par l’utilisation des Blocks en Objective-C. Leur similarité avec les expressions lambda de la programmation fonctionnelle que vous pouvez retrouver dans Java 8, Scala ou bien encore JavaScript est évidente. Cependant, nous ne sommes pas habitué avec Objective-C à penser ou bien écrire dans un style fonctionnel. Cependant, il existe des libraries qui permettent de faciliter l’usage de l’approche fonctionnelle. Plusieurs projets ont même fleuri depuis la mise à disposition des blocks avec la sortie d’iOS4.
En JavaScript, la librairie underscore.js est très appréciée par les développeurs web pour sa simplicité et son efficacité. Cette librairie a d’ailleurs tellement de succès qu’elle a traversé la frontière des langages pour être implémentée en Objective-C! Il en existe à ce jour au moins deux implémentations, toutes les deux sous license MIT.

Le projet Underscore.m semble fournir un support plus abouti des fonctionnalités proposées par la librairie JavaScript originale, et surtout propose un site documentaire complet qui permet de démarrer rapidement et de trouver un grand nombre d’exemples.

Installation

Pour démarrer un projet avec Underscore.m, rien de plus simple, il suffit d’utiliser CocoaPods que nous avons découvert dans un article précédent.

Pour rappel, si vous n’avez pas encore installé CocoaPods, il suffit de lancer les commandes suivantes pour installer l’outil (A condition d’utiliser une version 1.9 de Ruby):

$ gem install cocoapods
$ pod setup

(suite…)

Utilisation des Blocks en Objective-C

Utilisation des Blocks en Objective-C


Introduits en 2010 avec la sortie d’iOS4, les Blocks ont profondément changé la manière d’écrire des applications en Objectif-C.

L’implémentation de callbacks via la création de protocole est un procédé verbeux mais qui a l’avantage de rester simple à comprendre. Les blocks quant à eux ont une syntaxe déclarative moins évidente à appréhender de prime abord, mais sont bien plus expressifs et permettent d’éviter les allers et retours dans le code entre protocoles, interfaces et implémentations.

A travers cet article, je vous propose de découvrir les différences de styles qu’il existe entre l’usage des protocoles, plus classiques, et des blocks qui se veulent plus modernes.

La gestion d’événements dans iOS

Un programme informatique dans la plus simple de ses expressions un simple traitement exécutant de façon séquentielle une suite d’instructions. Cependant, la plupart du temps une application plus complexe aura à réagir à différents événements qu’ils proviennent d’interactions avec le réseau, avec le système de fichier ou bien encore avec la personne qui le commande via le clavier, la souris ou le touché. Le plus souvent ces événements sont notifiés au programme sous forme de callback.

Sous iOS, un callback résultant d’un événement peut prendre 3 formes:

  • Le callback de type Target-action: Lorsqu’un événement survient, un objet target est notifié par l’objet source de l’événement. Pour cela il va appeler un selecteur. Ce selecteur correspond à l’action. Les timers iOS implémentent ce mécanisme:
#import <foundation /Foundation.h>
#import "Logger.h"

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        Logger *logger = [[Logger alloc] init];

        NSTimer *timer : [NSTimer scheduledTimerWithTimeInterval: 1.0
                                                          target: logger
                                                        selector: @selector:(onTick:)
                                                        userInfo: nil
                                                         repeats: YES];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
    return 0;
}

(suite…)

Tour d’horizon des nouveautés du langage Objective-C

Tour d’horizon des nouveautés du langage Objective-C


L’Objective-C a connu ces dernières années différentes évolutions qui ont permis de donner un coup de jeune à un langage qui va fêter d’ici peu ses trente bougies. Pour y voir plus clair dans ces évolutions, je vous propose de (re)découvrir un bref résumé chronologique des évolutions apportées par Apple au langage  :

  • 2006 / 2007 : Apple annonce la révision 2.0 du langage lors du WWDC. Cette révision apporte de nombreuses nouveautés telles que le support des propriétés (On attend toujours pour Java …), des énumérations rapides, des déclarations optionnelles de méthodes dans les protocoles, ou bien encore des extensions de classes.
  • 2010 : Apple introduit une nouveauté comparable à la notation lambda en Java appelée Blocks. Ces blocs de codes ne sont pas de simple fonctions anonymes mais des closures: elles conservent l’accès aux données du contexte dans lequel elles ont été créées.
  • 2011 : Avec l’arrivée d’iOS 5, Apple a introduit la gestion automatique du comptage des références, également appelée ARC pour Automatic Reference Counting, qui a pour but de permettre aux développeurs de globalement s’affranchir des problématiques de gestion de la mémoire. Cette dernière évolution est un tel chamboulement que de nombreux projets ne l’ont pas encore adopté et continuent de fonctionner avec un comptage manuel des références.
  • 2012 : Apple introduit une syntaxe simplifiée via le support des Object Literals à partir d’OSX 10.8 et d’Xcode 4.4. Cette notation est cependant disponible uniquement pour les développeurs iOS utilisant le SDK 6.0.

Ces diverses évolutions ont contribué à moderniser le langage et simplifier son utilisation. Apple proposait d’ailleurs lors du dernier WWDC, deux sessions : l’une ayant pour objectif de présenter ces nouveautés, et l’autre de se familiariser avec afin de les intégrer dans les projets.

A travers différents exemples, je vous propose de découvrir certaines de ces simplifications / améliorations. Si vous souhaitez tester ces fonctionnalités vous pouvez vous équipez de la version 4.4 ou supérieur d’Xcode qui intègre la version 3.1 du compilateur Clang gérant ces nouveautés.

Définition

Un littéral est une déclaration dans le code source d’un logiciel permettant de représenter une valeur. Le littéral le plus connu est la représentation d’une chaîne de caractères dans un code source. Une simple déclaration de chaîne de caractères en Java, par exemple, permet d’instancier un objet String sans passer explicitement par un constructeur : sa construction / instanciation / initialisation est implicite. Le recours aux littéraux dans un code source a pour objectif de simplifier, et de rendre plus lisible et compréhensible un code source.

En Objective-C, la syntaxe littérale pour instancier un objet NSString est la suivante :

NSString *nickname = @"John Doe";

Vous pouvez cependant déclarer le même objet NSString via une syntaxe n’utilisant pas de littéraux :

NSString *nickname = [NSString stringWithCString:"John Doe" encoding:NSUTF8StringEncoding];

L’intérêt d’une telle notation saute tout de suite aux yeux. La déclaration d’un littéral NSString est similaire à celle d’un littéral C string standard, sauf qu’elle est préfixée par le caractère ‘@’.

(suite…)