• 20 heures
  • {0} Facile|{1} Moyenne|{2} Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

J'ai tout compris !

Mis à jour le 21/06/2013

Les principaux objets utilisés en Objective-C

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

En tant que programmeurs Objective-C, vous allez être amenés à dialoguer avec des méthodes de classes en leur envoyant des messages. Ce chapitre s'intéresse aux classes incontournables et aux méthodes qui vous seront les plus utiles.

Chaînes de caractères

Une chaîne de caractères est une suite de zéro, un ou plusieurs caractères. Voici quelques exemples de chaînes de caractères :

Ceci est une chaîne de caractères
123 est plus petit que 456
@ç/w&!

Dans une application destinée aux iPhone, iPod Touch ou iPad, les chaînes de caractères sont manipulées à travers la classe Cocoa Touch NSString :

NSString *maChaine;

Il se peut qu'un jour vous tombiez sur une variante de cette déclaration :

NSString * maChaine;
(NSString*) maChaine;
NSString* maChaine;

Ces trois déclarations sont strictement équivalentes à celle que je viens de vous présenter.

Si nécessaire, il est possible d'affecter une valeur à une chaîne lors de sa définition :

NSString *maChaine = @"Ceci est une chaîne de caractères";

Avez-vous remarqué le signe @ avant le début de la chaîne ? Il est là pour indiquer à Xcode que les caractères suivants sont une chaîne de caractères.

Et maintenant, nous allons voir comment manipuler les chaînes de caractères en étudiant quelques méthodes de la classe NSString.

Tester l'égalité de deux NSString

Il est souvent utile de comparer deux chaînes entre elles. Vous pensez peut-être qu'il suffit d'utiliser une instruction du type suivant :

if (chaine1 == chaine2)
{
// Traitement
}

Eh bien, ce serait trop simple ! En fait, cette instruction compare non pas le contenu mais l'adresse des deux chaînes. Rappelez-vous, lorsque vous définissez une nouvelle chaîne, vous le faites en créant un pointeur :

NSString *chaine1;

Heureusement, il existe une solution pour comparer simplement deux chaînes. Vous utiliserez pour cela la méthode isEqualToString de la classe NSString :

if ([chaine1 isEqualToString:chaine2])
{
// Traitement
}

Si cette syntaxe vous laisse perplexes, jetez un œil à la section « Appeler des méthodes » du chapitre précédent et tout deviendra plus clair. Pour ceux qui auraient la mémoire courte, les méthodes de classe sont appelées en utilisant la syntaxe suivante :

[objet methode:entrée];

Dans le cas qui nous occupe, la méthode isEqualToString est appliquée à l'objet chaine1 en lui transmettant l'objet chaine2 en entrée. Cette méthode retourne la valeur TRUE si les deux chaînes sont égales, FALSE dans le cas contraire.

Longueur d'un NSString

La longueur d'une chaîne est obtenue avec la méthode length de la classe NSString. Voici un exemple d'utilisation de cette méthode :

NSString *a = @"ceci est une chaîne";
NSLog(@"Longueur de la chaine : %i", [a length]);

L'instruction NSLog affiche le texte suivant dans le volet de débogage :

Longueur de la chaîne : 19

Concaténer deux NSString

Pour concaténer deux chaînes, c'est-à-dire pour les mettre bout à bout, vous utiliserez la méthode stringWithFormat :

NSString *chaine1=@"première partie";
NSString *chaine2= @" deuxième partie";
NSString *chaine3;
chaine3 = [NSString stringWithFormat:@"%@%@",chaine1,chaine2];
NSLog(@"%@",chaine3);

Les trois premières instructions ne devraient pas vous poser de problème. Pour tous ceux qui pensent que la quatrième ligne est incompréhensible, faisons quelques étapes intermédiaires.
L'objet NSString chaine3 a été défini à la ligne précédente. Pour lui affecter une valeur, il suffit de faire suivre son nom du signe = et de la valeur souhaitée : chaine3 = valeur;.

La valeur est obtenue en utilisant la méthode stringWithFormat de la classe NSString. Le début de l'expression est donc tout à fait clair : [NSString stringWithFormat ...].

La méthode stringWithFormat admet un paramètre de type NSString. Dans cet exemple, ce paramètre a pour valeur @"%@%@",chaine1,chaine2. Le signe @ devant le premier guillemet indique que la suite est une chaîne de caractères. Quant aux %@, ils se réfèrent aux éléments spécifiés juste après le deuxième guillemet. Ainsi, le premier %@ est remplacé par chaine1 et le deuxième par chaine2. Le résultat renvoyé est la concaténation des deux chaînes. L'instruction NSLog affiche donc le texte suivant dans le volet de débogage :

première partie deuxième partie

Définir une chaîne pendant l'exécution d'une l'application

Supposons que l'objet NSString maChaine soit défini et initialisé avec l'instruction suivante :

NSString *maChaine = @"Bonjour";

Pour initialiser un objet NSString à partir d'une chaîne de type char, vous utiliserez les instructions suivantes :

char *chaineC;
NSString *chaineObjC;
...
// Instructions qui initialisent la variable char chaineC
...
chaineObjC = [NSString stringWithString: chaineC];

Inversement, pour initialiser une chaîne de type char à partir d'un objet NSString, vous utiliserez les instructions suivantes :

const char *chaineC;
NSString *chaineObjC = @"Bonjour";
chaineC = [chaineObjC String];

Parcourir un NSString, caractère par caractère

Un jour ou l'autre, vous serez certainement confrontés à ce problème : comment isoler chacun des caractères contenus dans un objet NSString afin d'effectuer des comparaisons ou de leur appliquer un traitement individuel ?
La solution est des plus simples : il suffit d'appliquer de manière répétitive la méthode characterAtIndex à la chaîne.

NSString *chaine;
chaine = @"helloworld";
int i = chaine.length; // La variable i contient le nombre de caractères de la chaîne
int j;
char uneLettre;
for(j=0; j<i; j++) // Boucle de 0 à i en incrémentant j
{
uneLettre = [chaine characterAtIndex:j]; // Extraction d'un caractère de la chaîne
NSLog(@"La lettre en position %i est %c ", j, uneLettre);
}

La figure suivante représente le résultat dans la fenêter de débogage.

Le résultat s'affiche dans la fenêtre de débogage

Nombres

Nous allons ici parler des objets de classe NSNumber, qui peuvent laisser perplexe. En effet, pourquoi utiliser une classe dédiée à la manipulation des nombres alors que les types int, float, double, etc. sont déjà disponibles ?

Et pourtant, vous aurez besoin de la classe NSNumber dans plusieurs cas bien précis. Par exemple, pour convertir des types de données. Le type d'un objet NSNumber peut être facilement modifié en utilisant les méthodes floatValue, doubleValue, intValue, longValue, etc. Ici par exemple, un nombre entier est converti en un nombre double avec la méthode doubleValue :

NSNumber *unEntier = [NSNumber numberWithInteger:23];
float unDouble = [unEntier doubleValue];

La première instruction définit l'objet unEntier de type NSNumber et l'initialise avec la valeur entière 23. La deuxième instruction définit la variable unDouble de type float et lui affecte la conversion en un double de l'objet unEntier.

À la vue de ce code, vous vous sentez certainement désorientés. Ne vous en faites pas, tout deviendra plus clair au fur et à mesure de votre apprentissage. Pour l'instant, il vous suffit de savoir que les types numériques cohabitent avec la classe NSNumber, et que cette dernière est utile dans certains cas bien précis.

Dates et heures

Plusieurs classes sont associées à la manipulation des objets date et heure dans Objective-C : NSDate, NSCalendar, NSTimeZone, NSDateComponents, NSDateFormatter. Pour mieux appréhender ces différentes classes, rien de tel qu'un peu de code.

Affichage de la date courante

Ces quelques lignes de code affichent la date courante au format américain (en_US) et français (fr_FR) :

/* ---Définition de l'objet date et de sa mise en forme--- */
// Aujourd'hui
NSDate *date = [NSDate date];
NSDateFormatter *miseEnForme = [[NSDateFormatter alloc] init];
// Aucun affichage de l'heure
[miseEnForme setTimeStyle:NSDateFormatterNoStyle];
// Affichage de la date au format semi-abrégé
[miseEnForme setDateStyle:NSDateFormatterMediumStyle];
/* ---Affichage de la date au format US--- */
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[miseEnForme setLocale:usLocale];
NSLog(@"Date au format %@: %@", [[miseEnForme locale] localeIdentifier], [miseEnForme stringFromDate:date]);
/* ---Affichage de la date au format FR--- */
NSLocale *frLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"];
[miseEnForme setLocale:frLocale];
NSLog(@"Date au format %@: %@", [[miseEnForme locale] localeIdentifier], [miseEnForme stringFromDate:date]);

Et voici ce que ça donne dans la console :

[...] test[1527:207] Date au format en_US: Jun 7, 2011
[...] test[1527:207] Date for locale fr_FR: 7 juin 2011

Cette syntaxe est vraiment incroyable et j'ai peur d'être dépassé ! Est-ce que j'aurais raté un chapitre ?

Examinons le premier bloc d'instructions. La ligne 4 définit l'objet NSDate date (NSDate *date) et lui affecte la date courante ([NSDate date]).

NSDate *date = [NSDate date];

La ligne 5 définit l'objet miseEnForme de type NSDateFormatter. C'est par l'intermédiaire de cet objet que l'on définira un format d'affichage pour la date.

NSDateFormatter *miseEnForme = [[NSDateFormatter alloc] init];

La ligne 8 indique que l'heure ne doit pas être affichée. La méthode setTimeStyle est donc appliquée à l'objet miseEnForme en lui transmettant un paramètre :

[miseEnForme setTimeStyle:NSDateFormatterNoStyle];

Enfin, la quatrième instruction donne le format d'affichage de la date. Les messages autorisés pour la méthode setDateStyle sont :

  • NSDateFormatterNoStyle

  • NSDateFormatterShortStyle

  • NSDateFormatterMediumStyle

  • NSDateFormatterLongStyle

  • NSDateFormatterFullStyle

Je vous invite à modifier l'instruction en question afin d'observer les différents comportements de ces méthodes.

[miseEnForme setDateStyle:NSDateFormatterMediumStyle];

Examinons maintenant le deuxième bloc d'instructions.
La ligne 14 définit l'objet NSLocale usLocale et l'initialise au format en_US, c'est-à-dire anglais américain :

NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

La ligne suivante utilise la classe setLocale pour indiquer à l'objet NSDateFormatter miseEnForme que l'affichage devra se faire au format anglais américain :

[miseEnForme setLocale:usLocale];

Enfin, la ligne 16 affiche la date courante dans ce format. Le premier message entre crochets récupère l'identificateur de langue (en_US) et le deuxième la date au format miseEnForme :

NSLog(@"Date au format %@: %@", [[miseEnForme locale] localeIdentifier], [miseEnForme stringFromDate:date]);

Le troisième bloc d'instructions est très proche du deuxième, à ceci près qu'il demande l'affichage de la date au format français.

Création d'une date relative à la date système

La méthode initWithTimeIntervalSinceNow permet de créer un objet NSDate en lui appliquant un décalage par rapport à la date système. Le décalage peut être positif (pour définir une date postérieure à la date système) ou négatif (pour définir une date antérieure à la date système).
Examinez le code suivant :

NSDate *dateCourante = [NSDate date]; //Aujourd'hui
NSTimeInterval secondesParJour = 24 * 60 * 60;
NSDate *demain = [[NSDate alloc] initWithTimeIntervalSinceNow:secondesParJour];
NSDate *hier = [[NSDate alloc] initWithTimeIntervalSinceNow:-secondesParJour];

La première ligne définit l'objet NSDate dateCourante et y mémorise la date système.
La deuxième ligne définit l'objet NSTimeInterval secondesParJour et y mémorise le nombre de secondes contenues dans une journée.
La troisième ligne définit l'objet NSDate demain et y stocke la date système plus un jour. Pour cela, la méthode initWithTimeIntervalSinceNow lui est appliquée en lui transmettant la valeur secondesParJour. L'objet demain est donc initialisé avec la date qui suit le jour courant.
La quatrième ligne est très proche de la troisième, mais ici, le paramètre passé à la méthode initWithTimeIntervalSinceNow est égal à -secondesParJour. L'objet hier est donc initialisé avec la date qui précède le jour courant.

Définition d'une date autre que la date système

Pour définir une date différente de la date système, vous devez :

  1. définir et initialiser un objet NSDateComponents ;

  2. l'affecter à un objet NSDatevia un objet NSCalendar.

Tout ceci a l'air bien compliqué, mais vous allez voir qu'il n'en est rien en examinant le code suivant :

// Définition d'un objet NSDateComponents
NSDateComponents *nsDatePerso = [[NSDateComponents alloc] init];
[nsDatePerso setYear:2065];
[nsDatePerso setMonth:8];
[nsDatePerso setDay:12];
// Création d'un objet NSDate et affectation de l'objet nsDatePerso défini précédemment
NSDate *datePerso = [[NSCalendar currentCalendar] dateFromComponents:nsDatePerso];
NSLog(@"Date utilisateur : %@", datePerso);

Voici le résultat affiché dans la console :

[...] test[1680:207] Date utilisateur : 2065-08-11 22:00:00 +0000

Comme vous le voyez, aucune mise en forme NSFormatter n'a été appliquée à l'objet datePerso.

Examinons les instructions qui composent ce code.
La première instruction définit l'objet NSDateComponents nsDatePerso et réserve son emplacement en mémoire :

NSDateComponents *nsDatePerso = [[NSDateComponents alloc] init];

Les trois instructions suivantes initialisent les composants année, mois et jour de cet objet.

[nsDatePerso setYear:2065];
[nsDatePerso setMonth:8];
[nsDatePerso setDay:12];

Le deuxième bloc d'instructions définit un objet NSDate de nom datePerso (NSDate *datePerso). Cet objet est initialisé avec la date définie dans l'objet nsDatePerso (dateFromComponents:nsDatePerso) en passant par un objet NSCalendar ([NSCalendar currentCalendar]) :

NSDate *datePerso = [[NSCalendar currentCalendar] dateFromComponents:nsDatePerso];

Une variante pour définir une date autre que la date système

Pour définir et initialiser un objet NSDate avec une date différente de la date système, il est également possible d'utiliser une chaîne de caractères. Cette technique est plus simple que la précédente. Elle consiste à passer en paramètre la chaîne qui contient la date à la méthode dateFromString, qui elle-même est appliquée à un objet NSDateFormatter :

NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"dd-MM-yyyy"];
NSDate *uneDate = [df dateFromString:@"12-08-2011"];

La première instruction définit l'objet NSDateFormatter df et lui réserve un emplacement en mémoire :

NSDateFormatter* df = [[NSDateFormatter alloc]init];

La deuxième instruction définit le format utilisé dans l'objet NSDateFormatter :

[df setDateFormat:@"dd-MM-yyyy"];

Enfin, la troisième instruction affecte une date à l'objet NSDate uneDate en transmettant une chaîne à la méthode dateFromString de l'objet NSDateFormlatter df :

NSDate *uneDate = [df dateFromString:@"12-08-2011"];

Extraction des composants d'un objet NSDate

Pour accéder aux composants (jour, mois, année, heure, minute et seconde) d'une date au format NSDate, vous devez utiliser la méthode components: fromDate: d'un objet NSCalendar dans lequel vous aurez stocké la date.

À titre d'exemple, le code ci-dessous extrait le jour, le mois, l'année, l'heure, les minutes et les secondes de la date système et les affiche dans la console :

NSDate *date = [NSDate date]; //Aujourd'hui
NSCalendar *calendrier = [NSCalendar currentCalendar];
NSDateComponents *composants = [calendrier components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:date];
NSLog(@"Nous sommes le %i / %i / %i", [composants day], [composants month], [composants year]);
NSLog(@"Il est %i : %i : %i", [composants hour], [composants minute], [composants second]);

La première instruction crée l'objet NSDate date et y stocke la date système :

NSDate *date = [NSDate date]; //Aujourd'hui

La deuxième instruction crée l'objet NSCalendar calendrier :

NSCalendar *calendrier = [NSCalendar currentCalendar];

La troisième instruction crée l'objet NSDateComponents composants et lui affecte les composants suivants de l'objet NSDate date :

  • année : NSYearCalendarUnit

  • mois : NSMonthCalendarUnit

  • jour : NSDayCalendarUnit

  • heure : NSHourCalendarUnit

  • minutes : NSMinuteCalendarUnit

  • secondes : NSSecondCalendarUnit

Les deux dernières instructions affichent les composants de la date système dans la console, ce qui donne le résultat suivant :

[...] test[1897:207] Nous sommes le 7 / 6 / 2011
[...] test[1897:207] Il est  16 : 39 : 6

Ajouter ou soustraire des dates

Pour ajouter ou soustraire un certain nombre d'années, de mois et de jours à une date, vous devez créer un objet dateComponents, y stocker la valeur à ajouter ou soustraire et ensuite utiliser la méthode dateByAddingComponents:toDate pour ajuster la date d'origine.
À titre d'exemple, nous allons ajouter 1 an, 3 mois et 10 jours à la date système et afficher le résultat dans la console. Voici le code utilisé :

NSDate *date = [NSDate date]; //Aujourd'hui
NSDateComponents *leGap = [[NSDateComponents alloc] init];
[leGap setYear:1];
[leGap setMonth:3];
[leGap setDay:10];
NSDate *nouvelleDate = [[NSCalendar currentCalendar] dateByAddingComponents:leGap toDate:date options:0];
NSLog(@"Date système : %@", date);
NSLog(@"Nouvelle date : %@", nouvelleDate);

La date système puis la nouvelle date sont affichées dans la console :

[...] test[1995:207] Date système : 2011-06-07 14:59:53 +0000
[...] test[1995:207] Nouvelle date : 2012-09-17 14:59:53 +0000

Examinons les instructions utilisées.
La première ligne définit l'objet NSDate date et y stocke la date système :

NSDate *date = [NSDate date];

La deuxième ligne définit l'objet NSDateComponents leGap et réserve son emplacement en mémoire :

NSDateComponents *leGap = [[NSDateComponents alloc] init];

Les trois lignes suivantes initialisent le décalage souhaité dans l'objet leGap :

[leGap setYear:1];
[leGap setMonth:3];
[leGap setDay:10];

La nouvelle date est calculée dans l'objet NSDate nouvelleDate. Les composants définis dans l'objet leGap sont ajoutés (dateByAddingComponents:leGap) à l'objet NSDate date (toDate: date) :

NSDate *nouvelleDate = [[NSCalendar currentCalendar] dateByAddingComponents:leGap toDate:date options:0];

Calculer la différence entre deux dates

Il est parfois nécessaire de calculer la différence entre deux dates. En Objective-C, cela se fait en appliquant les méthodes fromDate et toDate à un objet NSCalendar. Voici le code :

NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"yyyy-MM-dd"];
NSDate *dateA = [NSDate date]; //Aujourd'hui
NSDate* dateB = [df dateFromString:@"2011-01-01"];
NSCalendarUnit calendrier = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *difference = [[NSCalendar currentCalendar] components:calendrier fromDate:dateA toDate:dateB options:0];
NSInteger mois = [difference month];
NSInteger jours = [difference day];
NSLog(@"Différence entre les deux dates : %i mois et %i jours.", mois,jours);

Examinons ce code.
Les deux premières instructions définissent et initialisent l'objet NSDateFormatter df :

NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"yyyy-MM-dd"];

Les deux instructions suivantes stockent la date courante ainsi qu'une autre date (celle du 01/01/2011) dans les objets NSDate dateA et dateB :

NSDate *dateA = [NSDate date]; //Aujourd'hui
NSDate* dateB = [df dateFromString:@"2011-01-01"];

L'instruction suivante définit les composants qui seront utilisés pour calculer la différence entre les deux dates (ici les années, les mois et les jours) :

NSCalendarUnit calendrier = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;

L'instruction suivante calcule la différence entre les deux dates. L'instruction est assez conséquente, alors prenez le temps de bien la comprendre. Dans la section « Extraction des composants d'un objet NSDate », vous avez appris à utiliser la méthode components: fromDate pour extraire les composants (année, mois, jour, heures, minutes, …) d'une date. Ici, nous allons utiliser la méthode components: fromDate: toDate: pour effectuer une soustraction entre deux dates et en extraire les composants.

Dans un premier temps, un objet NSCalendar est obtenu avec le message [NSCalendar currentCalendar].

La méthode components: fromDate: toDate: est alors exécutée. La différence entre les dates dateA et dateB est calculée (fromDate:dateA toDate:dateB), et seuls les composants définis dans l'objet NSCalendatUnit calendrier sont retournés. Le résultat est stocké dans l'objet NSDateComponents difference :

NSDateComponents *difference = [[NSCalendar currentCalendar] components:calendrier fromDate:dateA toDate:dateB options:0];

Il ne reste plus qu'à extraire les composants ans, mois et jour du résultat et à les stocker dans des objets NSInteger :

NSInteger ans = [difference year];
NSInteger mois = [difference month];
NSInteger jours = [difference day];

Il ne reste plus qu'à les afficher dans la console :

NSLog(@"Différence entre les deux dates : % ans %i mois et %i jours.", ans,mois,jours);

Temps nécessaire pour exécuter un bloc d'instructions

Pendant la mise au point d'une application, il peut être utile de calculer le temps nécessaire à l'exécution d'un bloc de code. Voici comment procéder :

  1. définissez un objet NSDate et initialisez-le avec la date courante juste avant le bloc de code dont vous voulez tester le temps d'exécution ;

  2. exécutez le bloc de code ;

  3. appliquez la méthode timeIntervalSinceNow à l'objet NSDate initialisé à l'étape 1 et mémorisez le résultat dans un objet NSTimeInterval.

Voici un exemple de code qui teste le temps nécessaire à l'affichage de 100 lignes dans la console :

NSDate *debut = [NSDate date]; //Date courante
//On affiche 100 lignes dans la console grâce à une boucle
int compteur;
for (compteur=1; compteur<100; compteur++)
{
NSLog(@"abc");
}
NSTimeInterval intervalle = [debut timeIntervalSinceNow]; //On calcule le temps d'exécution...
NSLog(@"Temps écoulé : %f", intervalle); //Et on l'affiche

La figure suivante représente les dernières informations affichées dans la console.

On calcul le temps que prennent 100 lignes à s'afficher dans la console

Tableaux

La classe NSArray est dédiée à la manipulation de tableaux (un tableau est un assemblage d'objets quelconques : c'est une façon de les ranger, comme dans une armoire). En programmation, on parle aussi d'array (d'où le nom de la classe NSArray).

Définir et initialiser un tableau

Pour créer un tableau contenant une chaîne de caractères, vous utiliserez l'instruction suivante :

NSArray *monTableau = [NSArray arrayWithObject :@"premier"];

Pour créer un tableau contenant un entier, vous utiliserez l'instruction suivante :

NSArray *monTableau = [NSArray arrayWithObject :[NSNumber numberWithInt: 10]];

Pour créer un tableau contenant plusieurs chaînes de caractères, vous utiliserez l'instruction suivante :

NSArray *monTableau = [NSArray arrayWithObjects :@"premier",@"deuxième",@"troisième",@"quatrième", nil];

Enfin, pour créer un tableau à partir d'un autre tableau, vous utiliserez l'instruction suivante :

NSArray *monTableau2 = [NSArray arrayWithArray :monTableau1];

Accéder aux objets contenus dans un tableau

Plusieurs méthodes très pratiques permettent d'accéder aux informations contenues dans un objet NSArray.

  • containsObject renvoie la valeur true si le tableau contient au moins un objet. Il renvoie la valeur false dans le cas contraire.

  • count retourne le nombre d'objets du tableau.

  • objectAtIndex retourne l'objet situé à l'index (c'est-à-dire à la position) spécifié dans le tableau.

  • lastObject retourne le dernier objet contenu dans le tableau, c'est-à-dire celui dont l'index est le plus élevé.

Pour clarifier ces méthodes, rien de tel que quelques exemples :

NSArray *monTableau = [NSArray arrayWithObjects :@"premier",@"deuxième",@"troisième",@"quatrième", nil];
NSLog(@"%@",monTableau);
NSLog(@"Objet qui se trouve à l'index 1 : %@", [monTableau objectAtIndex:1]);
if ([monTableau containsObject:@"premier"])
NSLog(@"L'objet premier a été trouvé dans le tableau");
else
NSLog(@"L'objet premier n'a pas été trouvé dans le tableau");
if ([monTableau containsObject:@"dixième"])
NSLog(@"L'objet dixième a été trouvé dans le tableau");
else
NSLog(@"L'objet dixième n'a pas été trouvé dans le tableau");
NSLog(@"Dernier objet du tableau : %@", [monTableau lastObject]);

Examinons ces instructions.
La première ligne définit l'objet NSArray monTableau et l'initialise avec quatre chaînes de caractères : premier, deuxième, troisième et quatrième :

NSArray *monTableau = [NSArray arrayWithObjects : @"premier",@"deuxième",@"troisième",@"quatrième", nil];

La deuxième instruction (NSLog(@"%@",monTableau);) affiche le contenu du tableau dans la console.

La troisième instruction affiche l'objet qui se trouve en position 1 (le deuxième donc, puisque l'index commence à 0) :

NSLog(@"Objet qui se trouve à l'index 1 : %@", [monTableau objectAtIndex:1]);

Et voici les informations retournées dans la console :

[...] test[1095:207] Objet qui se trouve à l'index 1 : deuxième

Le premier bloc if else utilise la méthode containsObject pour tester la présence de l'objet premier dans le tableau et affiche un message en conséquence :

if ([monTableau containsObject:@"premier"])
NSLog(@"L'objet premier a été trouvé dans le tableau");
else
NSLog(@"L'objet premier n'a pas été trouvé dans le tableau");

Ici, l'objet premier faisant partie du tableau, voici ce qu'affiche la console :

[...] test[1095:207] L'objet premier a été trouvé dans le tableau

Le bloc if else suivant utilise la méthode containsObject pour tester la présence de l'objet dixième dans le tableau et afficher un message en conséquence :

if ([monTableau containsObject:@"dixième"])
NSLog(@"L'objet dixième a été trouvé dans le tableau");
else
NSLog(@"L'objet dixième n'a pas été trouvé dans le tableau");

L'objet dixième ne faisant pas partie du tableau, voici ce qu'affiche la console :

[...] test[1095:207] L'objet dixième n'a pas été trouvé dans le tableau

Enfin, la dernière instruction affiche le dernier objet du tableau :

NSLog(@"Dernier objet du tableau : %@", [monTableau lastObject]);

Comme prévu, le dernier objet est la chaîne quatrième :

[...] test[1095:207] Dernier objet du tableau : quatrième

Passer en revue les objets contenus dans un tableau

Vous vous en doutez certainement, la lecture successive des différents objets contenus dans un tableau se fera dans une boucle. Les objets peuvent être retrouvés avec la méthode objectAtIndex ou avec la méthode objectEnumerator. Nous allons examiner tour à tour ces deux possibilités.

Avec la méthode objectAtIndex
NSArray *monTableau = [NSArray arrayWithObjects :@"premier",@"deuxième",@"troisième",@"quatrième", nil];
int nombreElements = [monTableau count];
for (int i = 0; i < nombreElements; i++)
{
NSLog(@"Objet de rang %i : %@", i, [monTableau objectAtIndex: i]);
}

La première instruction définit l'objet NSArray monTableau et y stocke quatre chaînes de caractères. Je ne vous remets pas le code, à ce stade vous devriez avoir compris.

La deuxième instruction définit l'entier nombreElements et y stocke le nombre d'éléments du tableau :

int nombreElements = [monTableau count];

La boucle for exécute l'instruction NSLog() autant de fois que le tableau contient d'objets :

for (int i = 0; i < nombreElements; i++)

L'instruction NSLog de la ligne 5 accède aux éléments du tableau en passant l'index de la boucle à la méthode objectAtIndex et en l'appliquant à l'objet monTableau :

NSLog(@"Objet de rang %i : %@", i, [monTableau objectAtIndex: i]);

Le résultat affiché dans la console est bien celui qu'on attendait :

[...] test2[1417:207] Objet de rang 0 : premier
[...] test2[1417:207] Objet de rang 1 : deuxième
[...] test2[1417:207] Objet de rang 2 : troisième
[...] test2[1417:207] Objet de rang 3 : quatrième
Avec la méthode objectEnumerator
NSArray *monTableau = [NSArray arrayWithObjects :@"premier",@"deuxième",@"troisième",@"quatrième", nil];
NSEnumerator *enumer = [monTableau objectEnumerator];
NSObject *obj;
while ((obj = [enumer nextObject]) != nil)
{
NSLog(@"Objet : %@", obj);
}

La première instruction définit l'objet NSArray monTableau et y stocke quatre chaînes de caractères.

La deuxième instruction crée l'objet enumer de type NSEnumerator et l'initialise avec un énumérateur basé sur l'objet monTableau :

NSEnumerator *enumer = [monTableau objectEnumerator];

Ce type d'objet permet de décrire très facilement des tableaux. Pour en savoir plus sur ce sujet, consultez l'aide en cliquant sur les mots NSEnumerator (1) et objectEnumerator (2), et si nécessaire en activant les icônes Hide or show the Utilities (3) et Show Quick Help (4), comme indiqué à la figure suivante.

Consultez l'aide

L'instruction suivante définit l'objet obj de type NSObject :

NSObject *obj;

En appliquant la méthode nextObject à l'objet NSEnumerator enumer, on obtient tour à tour tous les objets stockés dans le tableau monTableau. Lorsque tout le tableau a été parcouru, la méthode nextObject renvoie la valeur nil. La façon la plus simple de passer en revue tout le contenu du tableau consiste à utiliser une boucle while :

while ((obj = [enumer nextObject]) != nil)

Si l'objet renvoyé par la méthode nextObject est différent de nil, il est affiché dans la console :

NSLog(@"Objet : %@", obj);

Dans le cas contraire, la boucle while prend fin.
Voici le résultat affiché dans la console :

[...] test2[1507:207] Objet : premier
[...] test2[1507:207] Objet : deuxième
[...] test2[1507:207] Objet : troisième
[...] test2[1507:207] Objet : quatrième

Dictionnaires

Parfois, l'ordre dans lequel sont mémorisés les éléments importe peu. Ce qui importe plutôt, c'est d'associer chacun des objets mémorisés à un autre objet unique. Par exemple, il pourrait être intéressant de définir des couples nom/définition, ou encore nom/adresse. Les définitions ou adresses pourraient alors être retrouvées en fournissant le nom correspondant.

Les classes NSDictionary et NSMutableDictionary répondent parfaitement à cette problématique. Vous utiliserez un dictionnaire NSDictionary lorsque les objets à mémoriser sont immuables, c'est-à-dire lorsqu'ils ne sont pas modifiés après leur création et leur initialisation. Par contre, vous utiliserez un dictionnaire NSMutableDictionary lorsque les objets à mémoriser peuvent être modifiés après leur création et leur initialisation.

Création et initialisation d'un dictionnaire

Voici les instructions à utiliser :

NSDictionary *leDictionnaire = [NSDictionary dictionary];
NSMutableDictionary * leDictionnaire = [NSMutableDictionary dictionary];

Pour ajouter des éléments dans un dictionnaire, vous appliquerez la méthode setObject à l'objet NSDictionary ou NSMutableDictionary en lui transmettant le couple de valeurs à mémoriser :

[leDictionnaire setObject: @"une définition" forKey: @"une clé d'accès"];
[leDictionnaire setObject: @"une autre définition" forKey: @"une autre clé d'accès"];

Si vous le souhaitez, la méthode dictionaryWithObjectsAndKeys permet de regrouper la définition et l'initialisation d'un dictionnaire dans une seule instruction :

NSDictionary *leDictionnaire = [NSDictionary dictionaryWithObjectsAndKeys: @"Une définition", @"une clé", @"Une autre définition", @"une autre clé", nil];

Comme vous pouvez le voir, les objets stockés dans le dictionnaire sont séparés entre eux par des virgules et la valeur nil identifie la fin du dictionnaire.

Enfin, sachez qu'un dictionnaire peut être créé à partir de deux NSArray. Le premier doit contenir les objets à stocker (définitions ou adresses), le deuxième les clés associées (noms) :

NSArray *lesObjets = [NSArray arrayWithObjects: @"une définition", @"une autre définition", nil];
NSArray *lesCles = [NSArray arrayWithObjects: @"une clé", @"une autre clé", nil];
NSDictionary *leDictionnaire = [[NSDictionary alloc] initWithObjects: lesObjets forKeys: lesCles];

Méthodes relatives aux dictionnaires

Pour connaître le nombre d'entrées stockées dans un dictionnaire, il suffit d'appliquer la méthode count à l'objet dictionnaire :

NSLog (@"Nombre d'entrées mémorisées dans le dictionnaire = %i", [leDictionnaire count]);

Pour obtenir l'objet qui correspond à une clé donnée, vous utiliserez la méthode objectForKey :

NSLog (@"La clé 'une clé' correspond à la chaîne = '%@'", [leDictionnaire objectForKey: @"une clé d'accès"]);

Enfin, vous pouvez utiliser les méthodes removeObjectForKey et removeAllObjects pour supprimer, respectivement, l'entrée dont la clé est spécifiée ou toutes les entrées du dictionnaire :

[leDictionnaire removeObjectForKey: @"une clé"];
[leDictionnaire removeAllObjects];

Un exemple de code

Ce petit exemple de code commenté illustre les instructions dont nous venons de parler :

//On crée un dictionnaire
NSMutableDictionary * leDictionnaire = [NSMutableDictionary dictionary];
//On remplit le dictionnaire avec des couples adresse/nom
[leDictionnaire setObject: @"12 rue Guérin 75013 Paris" forKey: @"Pierre Jaquart"];
[leDictionnaire setObject: @"26 rue de la Place 75002 Paris" forKey: @"Eric Courteau"];
[leDictionnaire setObject: @"115 rue des pêcheurs 75005 Paris" forKey: @"Jean Bertier"];
[leDictionnaire setObject: @"2 place Mayeur 75012 Paris" forKey: @"Placido Perez"];
//On affiche le nombre d'entrées du dictionnaire
NSLog (@"Nombre d'entrées mémorisées dans le dictionnaire : %i", [leDictionnaire count]);
//On affiche une des entrées du dictionnaire
NSLog (@"Le nom 'Eric Courteau' correspond à l'adresse '%@'", [leDictionnaire objectForKey: @"Eric Courteau"]);
//On supprime une entrée du dictionnaire
[leDictionnaire removeObjectForKey: @"Jean Bertier"];
//On affiche le nombre d'entrées du dictionnaire, après la suppression d'une des entrées
NSLog (@"Nombre d'entrées mémorisées dans le dictionnaire : %i", [leDictionnaire count]);

Et voici ce qu'affiche la console :

[...] test[2996:f803] Nombre d'entrées mémorisées dans le dictionnaire : 4
[...] test[2996:f803] Le nom 'Eric Courteau' correspond à l'adresse '26 rue de la Place 75002 Paris'
[...] test[2996:f803] Nombre d'entrées mémorisées dans le dictionnaire : 3

Ensembles

Dans les sections précédentes, vous avez fait connaissance avec les tableaux et les dictionnaires. Les tableaux permettent de stocker des objets dans un certain ordre. Ces derniers peuvent alors être retrouvés par leur index. Les dictionnaires définissent des couples valeurs/clés. Les valeurs sont retrouvées en spécifiant les clés correspondantes.

Il existe une troisième façon de stocker des objets : en utilisant des ensembles, via la classe NSSet, vous pouvez mémoriser un empilement d'objets sans ordre particulier.

Création et initialisation d'un ensemble

Pour créer un ensemble qui contient un seul objet :

NSSet * monEnsemble = [NSSet setWithObject:[NSNumber numberWithInt:2]];

Pour créer un ensemble à partir d'un tableau :

NSSet * monEnsemble = [NSSet setWithArray:monTableau];

Pour créer un ensemble qui contient plusieurs objets :

NSSet * monEnsemble = [[NSSet alloc] initWithObjects:@"un",@"deux",@"trois",nil];

Méthodes relatives aux ensembles

Recherche d'un objet dans un ensemble

La méthode containsObject permet de savoir si un objet fait partie d'un ensemble. Si l'objet est trouvé, la valeur true est renvoyée par la méthode. Dans le cas contraire, c'est la valeur false qui est renvoyée.
Ici, l'objet deux est recherché dans l'ensemble monEnsemble. Un texte est affiché dans la console s'il est trouvé :

if ([monEnsemble containsObject:@"deux"])
{
NSLog (@"La chaîne deux a été trouvée dans l'ensemble");
}
Récupération d'un objet dans un ensemble

Pour récupérer un objet dans un ensemble, vous utiliserez la méthode member. Si l'objet est présent, il est renvoyé par la méthode. Dans le cas contraire, c'est la valeur nil qui est renvoyée.
Ici, l'objet deux est recherché dans l'ensemble monEnsemble. S'il existe, il est affiché dans la console :

id unMembre = [monEnsemble member:(@"deux")];
if (unMembre!=nil)
{
NSLog(@"Objet %@",unMembre);
}
Récupération des objets d'un ensemble

La méthode allObjects permet de récupérer tous les objets d'un ensemble sous la forme d'un NSArray :

NSArray *leTableau = [monEnsemble allObjects];

La méthode objectEnumerator permet de récupérer un NSEnumerator sur un ensemble :

NSEnumerator *enumer = [monEnsemble objectEnumerator];

Enfin, la méthode anyObject permet de récupérer un objet quelconque d'un ensemble :

id unObjetQuelconque = [monEnsemble anyObject];

En résumé

  • Les chaînes de caractères sont manipulées à travers la classe NSString. Pour définir une chaîne, utilisez l'instruction NSString *maChaine.

  • int, float, double, etc. ne sont pas les seuls types de données numériques. Vous pouvez aussi utiliser des objets de classe NSNumber dans certains cas particuliers, par exemple pour effectuer des conversions de données.

  • Les classes NSDate, NSCalendar, NSTimeZone, NSDateComponents et NSDateFormatter permettent de manipuler des objets date et heure. Vous pouvez définir une date en rapport (ou non) avec la date système, extraire les composantes d'un objet NSDate, ajouter ou soustraire des dates, calculer la différence entre deux dates, etc.

  • La classe NSArray est dédiée à la manipulation de tableaux. Lorsqu'un tableau a été défini, vous pouvez tester son contenu avec la méthode containsObject, et accéder aux objets qui le composent avec les méthodes objectAtIndex et objectEnumerator.

  • Les classes NSDictionary et NSMutableDictionary permettent de définir des dictionnaires. Pour initialiser un dictionnaire, vous utiliserez les méthodes setObject, dictionnaryWithObjectAndKeys et initWithObjects.

  • Pour mémoriser des objets en les empilant, vous utiliserez un ensemble. Lorsqu'un ensemble a été défini, vous pouvez tester si un objet en fait partie, récupérer un objet donné, un objet quelconque, tous les objets ou un énumérateur.

Exemple de certificat de réussite
Exemple de certificat de réussite