Développement d'une application iPhone

Introduction au langage Objective-C

Obtenir une licence

La première étape avant de se lancer dans le développement iPhone est de télécharger l’IDE Xcode. Il comprend de nombreux outils, comme un éditeur, un débogueur, un client cvs …
Une fois inscrit sur le site d'apple Xcode est téléchargeable. L’inscription inclut une licence de base. Cette licence de base qui est gratuite et permet de tester son application uniquement sur un émulateur iPhone. Il existe plusieurs programmes de licence pour faire du développement iPhone.

iOS Developer Standard Program :
Ce type de licence coûte 99$ par an et est destiné à un développeur seul. Elle permet de tester l’application sur un iPhone et de la déposer sur l’appStore.

iOS Developer Enterprise Program :

Cette licence est destinée aux entreprises et elle coute 299$. Elle permet à plusieurs développeurs de travailler sur le même projet et de le tester sur plusieurs iPhones.

iOS Developer University Program :

Cette licence est gratuite et est destinée aux universités ou écoles supérieures. Elle permet aux étudiants de tester les applications sur leur iPhone.

Caractéristiques

L’Objective-C a été créé par BRAD COX dans les années 80. Il souhaitait combiner la richesse du small talk un des premiers langages objet et de la rapidité du C. Pour une meilleure maintenabilité et lisibilité de l’application, il est essentiel au développeur de respecter les bonnes pratiques de codage en utilisant l’encapsulation, le polymorphisme et l’héritage

Héritage et protocole

L’Objective C est un langage objet à héritage simple. Dans ce langage la notion de polymorphisme est présente par l’intermédiaire des protocoles. Les protocoles en Objective C sont analogues aux interfaces en JAVA. Ci dessous le diagramme de classe simplifié de la classe NSString.

diagram

Donc la classe NSString est conforme au protocole NSCoding, NSCopying et NSMutableCopying.


Contrairement au JAVA oû tout hérite de la classe Object, en objective C, il faut explicitement indiquer l’héritage à la classe NSObjet, sinon le développeur commence une nouvelle hiérarchie de classe.

Les méthodes

Le premier point que nous abordons est la déclaration d'une méthode.

Une méthode de d’instance se déclare ainsi :

-(void)uneMethode;
-(void)uneMethode :(int)argumment1;

Une méthode de classe se déclare de la façon suivante :

+(void)uneMethodeDeClasse;

Appeler une méthode dans une classe, la syntaxe suivante est utilisée :

[receveur message :argument et :argumment2];

Les typages

L’objective C possède la particularité d’être typé mais pas fortement. En effet, si le développeur le souhaite il peut utiliser le typage dynamique. Pour utiliser le typage dynamique, le pointeur id est utilisé. Le type id est un pointeur générique.

id toto;

Mais le développeur peut aussi typer de façon statique

monObject *obj;

Création d’une classe

Une classe en objective C est définie par une interface un fichier .h et son implémentation associée à un fichier .m .

une classe une classe

Dans l’exemple suivant nous allons créer un objet ContactLocation. Nous allons d’abord regarder l’interface :

La première étape consiste à faire les imports adéquats et à déclarer l’interface. ContactLocation hérite de NSobject et est conforme au protocole MKAnnotation. MKAnnotation est utilisé pour afficher une annotation ( un petit point) sur une mapView ( carte google map). Ajouter ensuite les méthodes, les getters et setters par l’intermédiaire de la directive @property:

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>


@interface ContactLocation : NSObject<lMKAnnotation> {
	CLLocationCoordinate2D coordinate;
}

@property(nonatomic,assign) CLLocationCoordinate2D coordinate;

-(id)initWithCoordinate: (CLLocationCoordinate2D) coord;

@end

La directive @property permet de générer les getter et setter, elle peut prendre différents attributs qui permettent d'indiquer un champ en lecture seule ou encore non atomique.

La deuxième étape est la création du .m qui porte le même nom que l’interface. Les étapes clés sont :

//import
#import "ContactLocation.h"


@implementation ContactLocation

//getter setter
@synthesize coordinate;

//Constructor
-(id)initWithCoordinate:(CLLocationCoordinate2D) coord{
	self = [self init];

	
	if ( self ) {
        coordinate = coord;
		
    }
	
    return self;
}



// required if you set the MKPinAnnotationView's "canShowCallout" property to YES
- (NSString *)title
{
	return @"contact location";
}


- (void) dealloc
{
//  Liberer tout
//...
//appel à super dealloc
	[super dealloc];
}

La méthode dealloc est appelée à la libération de l’objet. Dans cette méthode nous devons libérer les pointeurs alloués.


Instanciation d’un objet

En objective C l’instanciation d’une classe se fait en deux étapes :

  1. Allocation : Un objet connaît sa taille. L’allocation se fait par l’intermédiaire de « alloc »
  2. Initialisation : Cette étape permet d’initialiser les attributs de l’objet.

Ci dessous un exemple

ContactLocation *loc = [[ContactLocation alloc]initWithCoordinate:phoneCoordinate];

Dans ce cas phoneCoordinate représente les coordonnées d’un numéro de téléphone.


Gestion de la mémoire

L’une des difficultés dans le développement d’application iPhone est la gestion correcte de la mémoire. Il n’existe pas de carbage collector, c’est au développeur de gérer manuellement la libération des objets alloués. Tout objet instancié possède un compteur de références retain supérieur à zéro. Dès que ce compteur atteint zéro l’objet est détruit. Les méthodes alloc et copy créent un objet avec un compteur de référence à 1. L’appel à retain augmente le compteur de référence de 1. Pour décrémenter le compteur il suffit de faire appel releasesur cette objet. La méthode dealloc sera appelée automatiquement quand le compteur arrive à zéro.

[loc release]

Il existe une méthode autorelease pour permettre de retourner un objet alloué d’une méthode.

(NSString *) newMyString(){
	NSString *myString = [[NSString alloc]initWithFormat:@"Prout"];
	[myString autorelease]
	return myString;
}



L’appel à une instance d’un objet venant d’être libéré provoquera une erreur. Il est fortement déconseillé d’appeler la méthode dealloc directement sur l’objet pour le libérer.

Afin de faciliter le développement il existe l’objet NSAutoreleasePool. Celui-ci permet de s’affranchir de l’appel à release. Ceci est particulièrement utile dans une boucle par exemple.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

...//allouer pleins d’objets
[pool release];

La non gestion de la mémoire provoque des « leak » ou fuites de mémoire. Dans son SDK, apple fournit Instrument, un outil efficace pour détecter les leaks.


L’outil Instrument

Instrument est un outil fourni dans le SDK d’apple avec XCode et c'est un profiler de code. Pour présenter Instrument, nous allons aborder les Leak qui correspondent à une fuite mémoire. Pour cette introduction au leak, nous n’allons pas aborder la création d’un nouveau projet iPhone. Nous allons écrire le code suivant qui permet d’afficher dans la console la date du jour dans la méthode qui est appelée au lancement de l’application :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
	NSDate *now = [[NSDate alloc] init];
	NSLog(@"Nous sommes le %@",now);
	   	//[now release];

    [window makeKeyAndVisible];
		
	
	
    return YES;
}

Nous avons volontairement commenté la fonction de libération de la mémoire. Maintenant nous lançons l’application :

new projet

Instrument se lance et affiche d’une barre rouge la fuite mémoire.

instrument

En cliquant sur le texte en bleu, nous voyons dans un premier temps l’adresse mémoire non libérée. Puis dans un second temps instrument, le texte en bleu nous montre la ligne de code où l’objet n’a pas été libéré avec un pourcentage.

good instrument

Maintenant, nous libérons correctement l’objet et relançons instrument :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
	NSDate *now = [[NSDate alloc] init];
	NSLog(@"Nous sommes le %@",now);
	
	[now release];
	   
    [window makeKeyAndVisible];
		
	   return YES;
}

Nous constatons qu’il n’y a plus de leak dans Instrument si nous le relançons :

noleak