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];