Comme Objective-C est basé sur le langage C, celui-ci emprunte la syntaxe et les structures de contrôle du C.
if (category == 40) { // Faire autre chose ici. }
switch (category) { case 1: NSLog(@"Catégorie 1"); break; case 2: NSLog(@"Catégorie 2"); case 3: case 4: NSLog(@"Catégorie 3 ou 4"); default: NSLog(@"Catégorie par défaut."); break; }
resultat = [monObjet maMethode:arg]
-(void)NomDeLaFonction:(int)Param1:(int)Param2 { }
En créant une classe dans Xcode, deux fichiers sont créés : Classe.h
et Classe.m
. Le fichier .h
est le header file, ou le fichier d'entêtes. Il sert à déclarer les attributs de la classe et les signatures des méthodes. Aucune opération, aucun calcul n'y est fait. Voici un exemple :
#import <Foundation/Foundation.h> @interface Chat : NSObject { //ivars (instance vars) int age; NSString *nom; } // methodes publiques - (void) miaule; - (void) setNom: (NSString *) n; @end
Le fichier .m
est l'implémentation du fichier d'entêtes.
#import "Chat.h" @implementation Chat - (void) miaule { NSLog(@"Miow, dit %@", nom); } - (void) setNom: (NSString *) n { nom = n; } @end
Pour utiliser la classe dans un programme principal :
#import <Foundation/Foundation.h> #import "Chat.h" int main (int argc, const char * argv[]) { Chat *a = [Chat new]; [a setNom:@"Garfield"]; Chat *b = [Chat new]; [b setNom:@"Edgar"]; [a miaule]; [b miaule]; return 0; }
Pour créer un objet, au lieu d'utiliser la méthode new
, il est plus commun d'utiliser une autre méthode en deux étapes :
Chat *garfield = [[Chat alloc] init];
Cette façon de faire représente bien qu'en Objective-C, l'instanciation se fait en deux étapes : d'abord l'allocation de mémoire et ensuite l'initialisation.
Chat *garfield = [Chat alloc]; garfield = [Chat init];
L'avantage d'utiliser la façon plus complexe d'instancier est qu'il est alors possible de spécialiser l'initialisation de l'objet.
NSString *titre = [[NSString alloc] initWithString:@"Ici le titre"];
Dans le fichier .h
après le bloc @interface
:
@property (nonatomic, retain) NSString *text; @property (readwrite,assign) int iVar;
Dans le fichier .m
, après le @implementation
:
@synthesize text;
Toutes les classes héritent de NSObject
. Ils ont donc les méthodes héritées tels que :
Pour obtenir de l'information à une classe sur elle-même :
Class maClasse = [monObjet class]; NSLog(@"Ma classe est %@ : ", [monObjet className]);
Test pour appartenance à une classe générale :
if ([monObjet isKindOfClass:[UIControl class]]) { // code... }
Il existe aussi isMemberOfClass
qui fonctionne de la même façon que isKindOfClass
.
Les sélecteurs identifient les méthodes par le nom. Conceptuellement semblable à un pointeur de méthode.
SEL action = [button action]; [button setAction:@selector(start:)];
Les sélecteurs incluent tous les deux-points (:), exemple :
-(void) setName:(NSString *) name age:(int) age;
aura comme sélecteur :
SEL sel = @selector(setName:age:);
Il est possible de déterminer si un objet répond à un certain sélecteur :
id obj; SEL sel = @selector(start:); if ([obj respondsToSelector:sel]) { [obj performSelector:sel withObject:self] }
La gestion de la mémoire peut être importante, surtout dans le développement d'applications iPhone, qui n'a pas de ramasse-miettes (garbage collector).
[garfield release];
Seulement dans le cas où l'on veut faire une opération spéciale, il est possible surcharger la méthode dealloc
qui est héritée de NSObject
. Ceci se fait dans le fichier d'implémentation de la classe, c'est-à-dire dans le fichier .m
. On a pas besoin d'ajouter la signature de la méthode dealloc
dans le fichier d'entêtes de la classe.
- (void) dealloc { NSLog(@"Je vais être détruit..."); [super dealloc]; }
Il est possible de demander au système de décider lui-même du moment opportun pour relâcher un objet. Cette pratique devrait être utilisée avec précaution.
- (c) CreateSomething { C *c = [[C alloca] init]; [c release]; return c; }
Peut être remplacé par :
- (c) CreateSomething { C *c = [[C alloca] init]; [c autorelease]; return c; }
L'objet c
sera alors placé dans un pool
et le système appellera automatiquement la méthode release
de cet objet. Le pool
d'objets est déclaré avec cette ligne de code :
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // le code... // et finalement : [pool drain]; return 0;
for (Person *person in array) { NSLog([person description]); }
NSLog(@"There are %i minutes in a year.", minutesInAYear);
NSString *msg = [[NSString alloc] initWithFormat:@"le répertoire home est '%@'", path];
Il peut arriver avec la gestion de la mémoire qu'il y ait une erreur de type EXC_BAD_ACCESS
:
Program received signal: "EXC_BAD_ACCESS".
Ça ne donne pas beaucoup d'information sur la cause de l'erreur. Généralement, c'est parce qu'un release
a été fait sur une instance, mais que cette variable qui pointait sur cette variable a été demandée.
Personne *a = [Personne alloc] init]; [a marche]; [a release]; // plus loin dans le code... [a autreMethode]; // EXC_BAD_ACCESS (on a pas nécessairement d'idée sur ce que représente a)
Pour obtenir plus d'informations pour débugger, on peut utiliser les Zombies.
NSZombieEnaled
avec la valeur YES
Il y aura toujours un problème, mais au moins plus d'informations seront disponibles pour aider à débugger. Par exemple, la variable a
qu'on ne pouvait deviner sa nature, sera maintenant disponible (dans ce cas, on verrait que a
est une Personne
).
Problème dans le format de la chaine : on essaie de mettre un int
dans un emplacement qui s'attend à une chaine (%@
au lieu de %d
).
NSProcessInfo *pinfo = [[NSProcessInfo alloc] init]; NSLog(@"Nom du processus courant : '%@' Process ID : '%@'", [pinfo processName], [pinfo processIdentifier]); //EXC_BAD_ACCESS [pinfo release];
NSURL *etsurl = [NSURL URLWithString:@"http://www.etsmtl.ca"]; // Création du dictionnaire NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; [dict setObject:etsurl forKey:@"ETS"]; NSLog(@"%@", dict); // valeurs à travers une boucle foreach NSArray *keys = [dict allKeys]; for (NSString *key in keys) { NSLog(@"%@ is %@",key, [dict objectForKey:key]); } [dict release];