Outils pour utilisateurs

Outils du site


developpement:mac:objectivec

Introduction

Comme Objective-C est basé sur le langage C, celui-ci emprunte la syntaxe et les structures de contrôle du C.

if

if (category == 40) {
  // Faire autre chose ici.
}

switch

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

Méthodes

Appeler une méthode

resultat = [monObjet maMethode:arg]

Définir une méthode

-(void)NomDeLaFonction:(int)Param1:(int)Param2 {
}

Classes

Créer une classe

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

Utiliser l'objet

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

Instanciation

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

Propriétés

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;

Introspection

Toutes les classes héritent de NSObject. Ils ont donc les méthodes héritées tels que :

  • className
  • isMemberOfClass

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.

Sélecteurs

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

Gestion de la mémoire

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

Utilisation de l'autorelease

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;

Structure et contrôle

Énumération

for (Person *person in array)
{
    NSLog([person description]);   
}

Chaines de caractères

Construire une chaîne de caractères

NSLog(@"There are %i minutes in a year.", minutesInAYear);
NSString *msg = [[NSString alloc] initWithFormat:@"le répertoire home est '%@'", path];

Caractéristiques de xcode

Débugging

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.

  1. Dans Xcode, aller dans la fenêtre du projet
  2. Ouvrir la section à gauche qui se nomme Executable
  3. Faire un clic droit sur le projet et faire Get Info
  4. Dans la nouvelle fenêtre, aller complètement en bas et cliquer sur le plus (+)
  5. Ajouter la variable d'environnement NSZombieEnaled avec la valeur YES

Fenêtre du projet

Fenêtre Get Info

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).

EXC_BAD_ACCESS

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

Exemples par classes

NSMutableDictionary

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

NSURL

NSURL *etsurl = [NSURL URLWithString:@"http://www.etsmtl.ca"];
[etsurl release];

Ressources

developpement/mac/objectivec.txt · Dernière modification : 2022/02/02 00:42 de 127.0.0.1