Objective-C: care este esența limbajului și locul său în dezvoltarea iOS

Autor: IT Sectr Publicat: 2026-02-09 Timp de citire: 8 min

Objective-C — un limbaj de programare cu expediere dinamică de mesaje, creat de Brad Cox în anii 1980. Apple a ales Objective-C ca limbaj principal pentru NeXTSTEP, iar apoi pentru iOS SDK. Programming With Objective-C — introducere în sintaxa mesajelor și gestionarea memoriei.

Principalele

  • Objective-C — o supermulțime strictă a C cu sintaxă de mesaje în paranteze pătrate și runtime dinamic
  • Message passing — apelarea metodei prin [object selector:argument] cu căutarea dinamică a implementării prin objc_msgSend
  • Categories — mecanism de adăugare a metodelor la clase existente fără moștenire și fără acces la codul sursă
  • Blocks — funcții anonime cu închidere, predecesor al Swift closures
  • ARC vs MRC — numărarea automată și manuală a referințelor pentru gestionarea memoriei

Ce este Objective-C?

Objective-C — un limbaj de programare care extinde C cu capacități de programare orientată pe obiecte în stil Smalltalk. Codul Objective-C se compilează prin LLVM sau GCC în cod mașină nativ, păstrând compatibilitatea completă inversă cu C — orice cod C este corect în Objective-C.

Apple a achiziționat NeXT (împreună cu Objective-C) în 1997. Limbajul a devenit baza Cocoa și Cocoa Touch — framework-urile pentru macOS și iOS. Din 2014, Apple promovează Swift ca înlocuitor, dar Objective-C rămâne critic pentru proiectele legacy și unele framework-uri de sistem. Potrivit Apple (WWDC 2024), aproximativ 35% din aplicațiile din App Store conțin încă cod Objective-C.

Caracteristica cheie — runtime dinamic. Spre deosebire de Swift, unde apelurile de metode se rezolvă la compilare, Objective-C trimite mesaje în timpul execuției prin funcția objc_msgSend. Aceasta permite suprascrierea metodelor din zbor (method swizzling), adăugarea dinamică a claselor și utilizarea forward invocation pentru selectori inexistenți.

Sintaxa: C + suprastructură orientată pe obiecte

Orice cod C este corect în Objective-C. Suprastructura orientată pe obiecte adaugă clase (@interface/@implementation), categorii, protocoale (@protocol) și tipizare dinamică (id). Fișierele au extensiile .m (implementare) și .h (antete).

Sintaxa mesajelor și expedierea dinamică

Sintaxa mesajelor — principala diferență a Objective-C față de limbile de tip C. În loc de object.method(argument) se folosește [object method:argument]. Fiecare mesaj trece prin objc_msgSend, care caută dinamic implementarea metodei în runtime.

objective-c
// Sintaxa mesajelor cu parametri numiți
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];

// Mesaje imbricate
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];

// Verificarea tipului prin instrospecție
if ([object isKindOfClass:[UIView class]]) {
    UIView *view = (UIView *)object;
    view.backgroundColor = [UIColor redColor];
}

Dynamic dispatch permite suprascrierea metodelor în runtime (method swizzling) — o tehnică puternică, dar periculoasă. De exemplu, framework-uri precum AFNetworking și Aspects folosesc swizzling pentru interceptarea apelurilor URLSession. Apple avertizează: swizzling poate perturba funcționarea framework-urilor de sistem dacă este folosit incorect.

Categorii și extensii de clase

Categories — o capacitate unică a Objective-C de a adăuga metode la clase existente (inclusiv sistemice, precum NSString și UIView) fără moștenire și fără acces la codul sursă. Categoriile se declară prin @interface ClassName (CategoryName).

objective-c
// Fișierul UIColor+Hex.h — categorie pentru UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end

// Fișierul UIColor+Hex.m — implementare
@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

Extensions (Class Extension) — un tip special de categorie, declarat în fișierul .m fără nume: @interface ClassName (). Spre deosebire de categorii, extensions pot adăuga nu doar metode, ci și ivar (variabile de instanță) și property. Extensions sunt folosite pentru ascunderea API-ului intern de modulele externe.

Blocuri (Blocks) — funcții anonime cu închidere

Blocks — funcții anonime în Objective-C, care capturează variabile din domeniul de vizibilitate extern. Sintaxa blocurilor: ^(int x) { return x * 2; }. Blocks sunt folosite în UIKit pentru handler-e de callback, în Grand Central Dispatch pentru sarcini asincrone și în colecțiile NSArray/NSDictionary pentru operații funcționale.

objective-c
// Declararea tipului de bloc
typedef void (^CompletionBlock)(BOOL success, NSError *error);

// Bloc ca parametru
- (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);
        }
    });
}

Gestionarea memoriei în blocuri este critică. Blocurile capturează self cu referință puternică, ceea ce creează retain cycle la utilizarea directă. Soluția — __weak typeof(self) weakSelf = self, cu verificare ulterioară în interiorul blocului. Această problemă este complet rezolvată în Swift prin listele de capturare [weak self].

ARC și MRC: gestionarea memoriei

Objective-C a parcurs drumul de la MRC (Manual Reference Counting) la ARC (Automatic Reference Counting). În MRC, programatorul apela manual retain (creșterea contorului), release (scăderea) și autorelease (release întârziat). Erorile în aceste apeluri duceau la scurgeri de memorie sau crash-uri din cauza dangling pointers.

OperațiuneMRCARC
Crearea obiectului[[Object alloc] init][[Object alloc] init]
Păstrarea referinței[object retain]Automat
Eliberarea[object release]Automat
Autoeliberarea[object autorelease]Automat (nu este necesar)
Referința Weak__weak nu exista__weak (nil automat)

ARC a fost introdus în Xcode 4.2 și LLVM 3.0 (2011). Compilatorul inserează automat retain/release la compilare, analizând durata de viață a obiectelor. ARC nu este garbage collection — este analiză statică cu inserții automate. Objective-C ARC este compatibil cu Swift ARC: ambele folosesc același sistem de numărare a referințelor la nivel de runtime.

Interacțiunea cu Swift prin Bridging Header

Utilizarea comună a Objective-C și Swift într-un singur proiect — o practică obișnuită pentru proiectele legacy. Apple oferă Bridging Header — un fișier generat automat prin care Swift vede clasele Objective-C, iar Objective-C vede clasele Swift moștenite de la NSObject.

objective-c
// ProjectName-Bridging-Header.h
// Swift vede aceste antete automat
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"

Migrarea de la Objective-C la Swift — un proces etapizat. Fișierele noi se scriu în Swift, cele vechi se refactorizează treptat. Bridging Header se generează automat la adăugarea primului fișier Swift într-un proiect Objective-C. Pentru vizibilitatea inversă (ObjC → Swift), Xcode generează fișierul -Swift.h care conține @interface pentru clasele Swift marcate cu @objc.

swift
// Clasă Swift vizibilă din Objective-C
@objc class SwiftRouter: NSObject {
    @objc func navigateToProfile(userId: Int) {
        // implementare
    }
}

Limitări: tipurile value Swift (struct, enum) nu sunt vizibile direct din Objective-C — trebuie împachetate în class cu @objc. Generics în Swift sunt limitat accesibile din Objective-C. Abordarea recomandată — scrieți cod nou în Swift, iar codul Objective-C existent refactorizați-l doar la modificarea funcționalității respective.

Runtime și method swizzling în Objective-C

Principalul avantaj al Objective-C față de Swift — acces complet la runtime. Method swizzling, înlocuirea implementării metodelor în timpul execuției, permite suprascrierea metodelor de sistem fără moștenire. Bibliotecile precum Aspects și JRSwizzle folosesc această capacitate pentru AOP (programare orientată pe aspecte) — monitorizare, analitică și logare.

Forward invocation — o altă capacitate runtime: dacă un obiect nu răspunde la selector, sistemul apelează forwardInvocation:, permițând redirecționarea mesajului către alt obiect. Aceasta stă la baza pattern-ului Proxy în Objective-C (NSProxy), utilizat pentru inițializare întârziată și obiecte distribuite.

Apple recomandă minimizarea utilizării trucurilor runtime în codul nou, preferând tipizarea statică a Swift. Totuși, în proiectele legacy, cunoașterea objc_msgSend, method_exchangeImplementations și objc_getAssociatedObject este necesară pentru întreținerea bazei de cod existente.

Property și Key-Value Observing

Objective-C suportă property ca zahăr sintactic peste ivar cu gettere/settere. Modificatorii atomic/nonatomic, strong/weak/copy, readonly/readwrite și assign/retain determină comportamentul memoriei și siguranța firelor de execuție. Key-Value Observing (KVO) — mecanism de observare a modificărilor proprietăților încorporat în runtime: orice obiect se poate abona la modificările proprietăților altui obiect prin addObserver.

Întrebări frecvente

Ce este sintaxa mesajelor în Objective-C?

Apelarea metodei arată ca [object selector:argument]. Mesajul trece prin objc_msgSend, care găsește dinamic implementarea în runtime. Selectorul este numele metodei (@selector(methodName)), nu un pointer către funcție. Aceasta permite swizzling și forward invocation.

Cu ce diferă categoriile (Categories) de extensii (Extensions)?

Category (@interface ClassName (Name)) adaugă metode la orice clasă (inclusiv sistemice) fără moștenire. Extension (@interface ClassName ()) se declară în fișierul .m și poate adăuga property și ivar. Category nu poate adăuga ivar, extension — poate.

Ce sunt blocurile (Blocks) în Objective-C?

Blocks — funcții anonime cu sintaxa ^(parametri) { corp }, care capturează variabile din context. Analogul lambda în C++ și closures în Swift. Necesită __weak pentru prevenirea retain cycles la capturarea self. Folosite în UIKit, GCD și Foundation.

Care este diferența dintre ARC și MRC?

MRC — numărarea manuală a referințelor: programatorul apelează retain, release, autorelease. ARC — automată: compilatorul inserează retain/release pe baza analizei statice. ARC nu este GC — obiectele se eliberează imediat la zeroirea contorului. ARC suportă modificatorii __weak și __strong.

Se pot folosi Objective-C și Swift în același proiect?

Da, prin Bridging Header. Swift vede Objective-C prin acest antet, Objective-C vede Swift prin -Swift.h. Clasele Swift trebuie să moștenească NSObject și să fie marcate cu @objc. Struct și enum din Swift nu sunt vizibile direct pentru Objective-C.

Concluzii

  • Objective-C — o supermulțime strictă a C cu runtime dinamic și sintaxă de mesaje pentru Cocoa/Cocoa Touch
  • Message passing — apeluri prin [object method] cu expediere dinamică prin objc_msgSend și posibilitatea de swizzling
  • Categories — adăugarea de metode la clase existente fără moștenire, inclusiv clasele sistemice Apple
  • Blocks — funcții anonime cu închidere, care necesită __weak pentru prevenirea retain cycles
  • ARC vs MRC — evoluția de la retain/release manual la numărarea automată a referințelor prin compilator
  • Bridging Header — mecanism de lucru comun Swift și Objective-C într-un singur proiect pentru migrare treptată
  • Semnificația legacy — aproximativ 35% din aplicațiile App Store conțin cod Objective-C care necesită suport

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și