Mouviciel

Création d'applications pour Mac OS X

Les coulisses d'un développeur Mac

Délégation en Cocoa, être et avoir — Première partie

Publié le jeudi 4 septembre 2008, 6 commentaires

De nombreuses classes en Cocoa ont la possibilité de modifier leur comportement grâce au mécanisme de la délégation : Une instance d'une telle classe peut accueillir un objet qui souhaite être son délégué. Elle lui envoie alors certains messages, nommés méthodes déléguées, que cet objet sera libre de traiter.

Ainsi il y a deux facettes à la délégation :

Ce deuxième point sera le sujet de la deuxième partie.

Être un objet délégué

La plupart du temps, le développeur s'intéresse à enrichir ou à personnaliser le comportement d'un objet qui accepte d'avoir un objet délégué. Par exemple, il souhaitera que la fenêtre principale de son application soit redimensionnée selon des règles qu'il aura fixées.

Justement la classe NSWindow dispose de la méthode déléguée -windowWillResize:toSize: qui est envoyée à l'objet délégué de la fenêtre chaque fois que la fenêtre s'apprête à être redimensionnée. Il suffit que l'objet délégué réponde à cette méthode, et il pourra mettre son grain de sel dans le redimensionnement de la fenêtre.

Voici comment cela se passe.

Nous allons réaliser ensemble une petite application Cocoa dont l'unique fonction est de conserver les proportions de sa fenêtre lorsqu'elle est redimensionnée.

Tout d'abord, créez dans Xcode un nouveau projet d'application Cocoa. Nommez-le Delegate. Ajoutez une classe à ce projet : Menu File—New File..., puis Objective-C class. Nommez-la windowController.m et choisissez de créer aussi windowController.h. Il s'agit du contrôleur de la fenêtre, qui agira pour elle en qualité de délégué.

Ensuite, ouvrez le fichier qui décrit l'interface graphique MainMenu.xib (ou MainMenu.nib si vous n'avez pas une version récente d'Xcode). Nous allons y ajouter le contrôleur que nous venons de créer et le déclarer comme délégué de la fenêtre principale. Si ce n'est pas déjà fait, ouvrez la palette Library (cmd-shift-L) et la palette Inspector (cmd-shift-I).

Dans la palette Library trouvez l'élément Object de classe NSObject (c'est un cube bleu sans sphère autour) et faites-le glisser dans la fenêtre nommée MainMenu.xib (English). Cette fenêtre contient la description complète de l'interface graphique de l'application.

Assurez-vous que l'objet que vous venez de faire glisser est sélectionné, puis dans la palette Inspector choisissez l'onglet Identity (c'est un signe i dans un cercle). Dans la rubrique Class Identity Choisissez la classe windowController (c'est la classe que nous avonc créée, normalement elle est à la fin de la liste déroulante).

À ce stade, nous venons de créer une instance de windowController directement dans l'interface graphique. Nous allons maintenant lier cet objet à la fenêtre de l'application en le déclarant délégué de la fenêtre. Cela se passe encore dans Interface Builder

À l'intérieur de la fenêtre MainMenu.xib (English) localisez la fenêtre de l'application, elle s'appelle Window (Window). Réalisez un ctrl-drag depuis son icône jusque vers l'objet windowController (placez la souris sur l'icône de la fenêtre de l'application, pressez la touche ctrl puis le bouton de la souris, et sans relâcher déplacez la souris jusque sur l'icône de notre nouvel objet, maintenant relâchez).

Un petit menu noir semi-transparent apparaît, il est intitulé Outlets et contient un unique élément nommé delegate. Nous y voici ! Sélectionnez cet élément. Et voilà : notre windowController est devenu le délégué de la fenêtre de l'application. Sauvez MainMenu.xib (cmd-S) et revenez à Xcode.

Vérifions que cela marche comme nous le souhaitons : faisons en sorte que notre délégué accomplisse sa tâche de délégué. Modifiez le fichier windowController.m de la façon suivante (les modifications sont en gras) :

//
//  windowController.m
//  Delegate
//
//  Created by mouviciel on 04/09/08.
//  Copyright 2008 Mouviciel. All rights reserved.
//

#import "windowController.h"


@implementation windowController

- (NSSize)windowWillResize:(NSWindow *)window
                    toSize:(NSSize)proposedFrameSize
{
    NSLog(@"La taille demandée est: %@",
          [NSValue valueWithSize:proposedFrameSize]);
    return proposedFrameSize;
}

@end

Sauvez (cmd-S), compilez et lancez (Build and Go). Si la console n'apparaît pas (c'est une fenêtre avec à l'intérieur un texte semblable à : [Session started at 2008-09-04 22:16:09 +0200.]), pressez cmd-shift-R. Essayez de redimensionner la fenêtre de notre application Delegate et observez la console. Si tout se passe comme prévu, vous devriez voir une série de messages de la forme :

[Session started at 2008-09-04 22:21:31 +0200.]
2008-09-04 22:21:34.264 Delegate[20657:10b] Taille: NSSize: {482, 382}
2008-09-04 22:21:34.280 Delegate[20657:10b] Taille: NSSize: {485, 382}
2008-09-04 22:21:34.297 Delegate[20657:10b] Taille: NSSize: {491, 382}

Félicitations ! Vous venez de créer un objet délégué qui agit pour le compte d'un objet délégateur. Je vous laisse le soin de faire évoluer cette application de telle sorte que la largeur de la fenêtre soit exactement le double de sa hauteur (un indice : la taille proposedFrameSize est la taille demandée par l'utilisateur qui redimensionne la fenêtre, la valeur retournée par la méthode est la taille qui sera réellement donnée à la fenêtre).

Vous l'avez sans doute compris, la deuxième partie illustrera l'autre facette de la délégation, à savoir : avoir un objet délégué.

Commentaires

lamjed

Le lundi 9 mai 2011 à 12:42

Merci pour cette simple et claire explication

Mouviciel

Le lundi 9 mai 2011 à 20:02

Je suis heureux que cet article puisse aider quelqu'un plus de deux ans après sa rédaction !

claude

Le lundi 12 mars 2012 à 05:12

wow, merci bc !

me

Le samedi 28 avril 2012 à 11:42

sous xcode 3.2 , ca marche pas cette methode ,

language de merdeeeeeeee

sigmacode

Le samedi 28 mars 2015 à 15:38

Et une aide de plus :) (avec Xcode 6.2)
merci beaucoup

tni

Le mercredi 1 juin 2016 à 20:12

Merci pour l article

Ajoutez un commentaire

Les commentaires sont destinés à répondre en public à l'article visé et à ses commentaires déjà publiés. C'est pourquoi seul un pseudonyme vous est demandé ici. Si vous souhaitez échanger avec moi en privé, merci de me laisser un message via le menu contact en haut de la page.

Archive

Rubriques

Abonnement