Objective-C : l'essence du langage et sa place dans le développement iOS

Auteur : IT Sectr Publié le : 2026-02-09 Temps de lecture : 8 min

Objective-C est un langage de programmation avec répartition dynamique de messages, créé par Brad Cox dans les années 1980. Apple a choisi Objective-C comme langage principal pour NeXTSTEP, puis pour le SDK iOS. Programming With Objective-C — une introduction à la syntaxe de messages et à la gestion de la mémoire.

Points clés

  • Objective-C — un sur-ensemble strict de C avec une syntaxe de messages entre crochets et un runtime dynamique
  • Message passing — appels de méthode via [object selector:argument] avec recherche dynamique d'implémentation via objc_msgSend
  • Categories — mécanisme pour ajouter des méthodes aux classes existantes sans héritage et sans accès au code source
  • Blocks — fonctions anonymes avec fermetures, prédécesseur des closures Swift
  • ARC vs MRC — comptage automatique et manuel de références pour la gestion de la mémoire

Qu'est-ce que Objective-C ?

Objective-C est un langage de programmation qui étend C avec des capacités de programmation orientée objet dans le style Smalltalk. Le code Objective-C est compilé via LLVM ou GCC en code machine natif, conservant une compatibilité ascendante totale avec C — tout code C est valide en Objective-C.

Apple a acquis NeXT (avec Objective-C) en 1997. Le langage est devenu la base de Cocoa et Cocoa Touch — les frameworks pour macOS et iOS. Depuis 2014, Apple promeut Swift comme remplacement, mais Objective-C reste d'une importance cruciale pour les projets legacy et certains frameworks système. Selon Apple (WWDC 2024), environ 35 % des applications de l'App Store contiennent encore du code Objective-C.

La caractéristique clé est le runtime dynamique. Contrairement à Swift, où les appels de méthode sont résolus à la compilation, Objective-C envoie des messages à l'exécution via la fonction objc_msgSend. Cela permet de redéfinir des méthodes à la volée (method swizzling), d'ajouter dynamiquement des classes et d'utiliser forward invocation pour des sélecteurs inexistants.

Syntaxe : C + extension orientée objet

Tout code C est valide en Objective-C. L'extension orientée objet ajoute des classes (@interface/@implementation), des catégories, des protocoles (@protocol) et le typage dynamique (id). Les fichiers ont les extensions .m (implémentation) et .h (en-têtes).

Syntaxe de messages et répartition dynamique

La syntaxe de messages est la principale différence entre Objective-C et les langages de type C. Au lieu de object.method(argument), on utilise [object method:argument]. Chaque message passe par objc_msgSend, qui cherche dynamiquement l'implémentation de la méthode dans le runtime.

objective-c
// Syntaxe de messages avec paramètres nommés
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];

// Messages imbriqués
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];

// Vérification de type via introspection
if ([object isKindOfClass:[UIView class]]) {
    UIView *view = (UIView *)object;
    view.backgroundColor = [UIColor redColor];
}

La répartition dynamique permet de redéfinir des méthodes à l'exécution (method swizzling) — une technique puissante mais dangereuse. Par exemple, des frameworks comme AFNetworking et Aspects utilisent le swizzling pour intercepter les appels URLSession. Apple prévient : le swizzling peut casser les frameworks système s'il est mal utilisé.

Catégories et extensions de classe

Les Catégories sont une fonctionnalité unique d'Objective-C qui permet d'ajouter des méthodes aux classes existantes (y compris les classes système comme NSString et UIView) sans héritage et sans accès au code source. Les catégories sont déclarées via @interface ClassName (CategoryName).

objective-c
// Fichier UIColor+Hex.h — catégorie pour UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end

// Fichier UIColor+Hex.m — implémentation
@implementation UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex {
    CGFloat r = ((hex >> 16) & 0xFF) / 255.0;
    CGFloat g = ((hex >> 8) & 0xFF) / 255.0;
    CGFloat b = (hex & 0xFF) / 255.0;
    return [self colorWithRed:r green:g blue:b alpha:1.0];
}
@end

Les Extensions (Class Extension) sont un type spécial de catégorie déclarée dans un fichier .m sans nom : @interface ClassName (). Contrairement aux catégories, les extensions peuvent ajouter non seulement des méthodes mais aussi des ivar (variables d'instance) et des propriétés. Les extensions sont utilisées pour cacher l'API interne aux modules externes.

Blocs (Blocks) — fonctions anonymes avec fermetures

Les Blocs sont des fonctions anonymes en Objective-C qui capturent les variables de la portée externe. Syntaxe des blocs : ^(int x) { return x * 2; }. Les blocs sont utilisés dans UIKit pour les gestionnaires de callback, dans Grand Central Dispatch pour les tâches asynchrones et dans les collections NSArray/NSDictionary pour les opérations fonctionnelles.

objective-c
// Déclaration de type de bloc
typedef void (^CompletionBlock)(BOOL success, NSError *error);

// Bloc comme paramètre
- (void)fetchDataWithCompletion:(CompletionBlock)completion {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL result = [weakSelf processData];
        if (completion) {
            completion(result, nil);
        }
    });
}

La gestion de la mémoire dans les blocs est d'une importance cruciale. Les blocs capturent self avec une référence forte, créant un retain cycle lorsqu'ils sont utilisés directement. La solution est __weak typeof(self) weakSelf = self, suivie d'une vérification à l'intérieur du bloc. Ce problème est entièrement résolu en Swift via les capture lists [weak self].

ARC et MRC : gestion de la mémoire

Objective-C a évolué de MRC (Manual Reference Counting) à ARC (Automatic Reference Counting). En MRC, le développeur appelait manuellement retain (incrémenter le compteur), release (décrémenter) et autorelease (libération différée). Les erreurs dans ces appels entraînaient des fuites de mémoire ou des plantages dus à des pointeurs pendants.

OpérationMRCARC
Création d'objet[[Object alloc] init][[Object alloc] init]
Rétention de référence[object retain]Automatiquement
Libération[object release]Automatiquement
Autolibération[object autorelease]Automatiquement (non requis)
Référence faible__weak n'existait pas__weak (nil automatique)

ARC a été introduit dans Xcode 4.2 et LLVM 3.0 (2011). Le compilateur insère automatiquement retain/release à la compilation en analysant la durée de vie des objets. ARC n'est pas un ramasse-miettes — c'est une analyse statique avec des insertions automatiques. L'ARC d'Objective-C est compatible avec l'ARC de Swift : les deux utilisent le même système de comptage de références au niveau du runtime.

Interopérabilité avec Swift via Bridging Header

L'utilisation conjointe d'Objective-C et de Swift dans un même projet est une pratique courante pour les projets legacy. Apple fournit le Bridging Header — un fichier généré automatiquement grâce auquel Swift voit les classes Objective-C, et Objective-C voit les classes Swift qui héritent de NSObject.

objective-c
// ProjectName-Bridging-Header.h
// Swift voit ces en-têtes automatiquement
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"

La migration d'Objective-C vers Swift est un processus progressif. Les nouveaux fichiers sont écrits en Swift, les anciens sont progressivement refactorisés. Le Bridging Header est généré automatiquement lors de l'ajout du premier fichier Swift à un projet Objective-C. Pour la visibilité inverse (ObjC → Swift), Xcode génère un fichier <ProjectName>-Swift.h contenant les déclarations @interface pour les classes Swift marquées avec @objc.

swift
// Classe Swift visible depuis Objective-C
@objc class SwiftRouter: NSObject {
    @objc func navigateToProfile(userId: Int) {
        // implémentation
    }
}

Limitations : les types valeur de Swift (struct, enum) ne sont pas directement visibles depuis Objective-C — ils doivent être encapsulés dans une classe avec @objc. Les génériques de Swift ont une accessibilité limitée depuis Objective-C. L'approche recommandée est d'écrire le nouveau code en Swift et de refactoriser le code Objective-C existant uniquement lors de la modification de la fonctionnalité correspondante.

Runtime et Method Swizzling en Objective-C

Le principal avantage d'Objective-C par rapport à Swift est l'accès complet au runtime. Le method swizzling, qui remplace les implémentations de méthodes à l'exécution, permet de redéfinir des méthodes système sans héritage. Des bibliothèques comme Aspects et JRSwizzle utilisent cette capacité pour l'AOP (programmation orientée aspect) — surveillance, analyse et journalisation.

Forward invocation est une autre fonctionnalité du runtime : si un objet ne répond pas à un sélecteur, le système appelle forwardInvocation:, permettant de transmettre le message à un autre objet. C'est la base du pattern Proxy en Objective-C (NSProxy), utilisé pour l'initialisation paresseuse et les objets distribués.

Apple recommande de minimiser l'utilisation des astuces de runtime dans le nouveau code, préférant le typage statique de Swift. Cependant, dans les projets legacy, la connaissance de objc_msgSend, method_exchangeImplementations et objc_getAssociatedObject est nécessaire pour maintenir la base de code existante.

Propriétés et Key-Value Observing

Objective-C prend en charge les propriétés comme sucre syntaxique sur les ivar avec getters/setters. Les modificateurs atomic/nonatomic, strong/weak/copy, readonly/readwrite et assign/retain déterminent le comportement mémoire et la sécurité des threads. Key-Value Observing (KVO) est un mécanisme d'observation des changements de propriétés, intégré dans le runtime : tout objet peut s'abonner aux changements de propriétés d'un autre objet via addObserver.

Foire aux questions

Qu'est-ce que la syntaxe de messages en Objective-C ?

Un appel de méthode ressemble à [object selector:argument]. Le message passe par objc_msgSend, qui trouve dynamiquement l'implémentation dans le runtime. Un sélecteur est un nom de méthode (@selector(methodName)), pas un pointeur de fonction. Cela permet le swizzling et forward invocation.

En quoi les Catégories diffèrent-elles des Extensions ?

Une Catégorie (@interface ClassName (Name)) ajoute des méthodes à toute classe (y compris les classes système) sans héritage. Une Extension (@interface ClassName ()) est déclarée dans un fichier .m et peut ajouter des propriétés et des ivars. Une Catégorie ne peut pas ajouter d'ivars, mais une Extension le peut.

Que sont les Blocs (Blocks) en Objective-C ?

Les Blocs sont des fonctions anonymes avec la syntaxe ^(paramètres) { corps }, capturant les variables du contexte. Ils sont analogues aux lambdas en C++ et aux closures en Swift. Ils nécessitent __weak pour prévenir les retain cycles lors de la capture de self. Ils sont utilisés dans UIKit, GCD et Foundation.

Quelle est la différence entre ARC et MRC ?

MRC est le comptage manuel de références : le programmeur appelle retain, release, autorelease. ARC est automatique : le compilateur insère retain/release basé sur une analyse statique. ARC n'est pas un GC — les objets sont libérés immédiatement lorsque le compteur atteint zéro. ARC prend en charge les modificateurs __weak et __strong.

Peut-on utiliser Objective-C et Swift dans le même projet ?

Oui, via un Bridging Header. Swift voit Objective-C à travers cet en-tête, Objective-C voit Swift via <ProjectName>-Swift.h. Les classes Swift doivent hériter de NSObject et être marquées avec @objc. Les struct et enum de Swift ne sont pas directement visibles par Objective-C.

Résumé

  • Objective-C — un sur-ensemble strict de C avec runtime dynamique et syntaxe de messages pour Cocoa/Cocoa Touch
  • Message passing — appels via [object method] avec répartition dynamique via objc_msgSend et capacité de swizzling
  • Catégories — ajout de méthodes aux classes existantes sans héritage, y compris les classes système d'Apple
  • Blocs — fonctions anonymes avec fermetures, nécessitant __weak pour prévenir les retain cycles
  • ARC vs MRC — évolution du retain/release manuel au comptage automatique de références via le compilateur
  • Bridging Header — mécanisme pour que Swift et Objective-C travaillent ensemble dans un projet pour une migration progressive
  • Importance legacy — environ 35 % des applications de l'App Store contiennent du code Objective-C nécessitant de la maintenance

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi