Objective-C — programovací jazyk s dynamickým odesíláním zpráv, vytvořený Bradem Coxem v 80. letech 20. století. Apple zvolil Objective-C jako hlavní jazyk pro NeXTSTEP a později pro iOS SDK. Programming With Objective-C — úvod do syntaxe zpráv a správy paměti.
Hlavní body
Objective-C — programovací jazyk rozšiřující C o možnosti objektově orientovaného programování ve stylu Smalltalk. Kód v Objective-C se překládá pomocí LLVM nebo GCC do nativního strojového kódu, přičemž si zachovává plnou zpětnou kompatibilitu s C — jakýkoli C kód je v Objective-C správný.
Apple koupil NeXT (spolu s Objective-C) v roce 1997. Jazyk se stal základem Cocoa a Cocoa Touch — frameworků pro macOS a iOS. Od roku 2014 Apple propaguje Swift jako náhradu, ale Objective-C zůstává kriticky důležitý pro legacy projekty a některé systémové frameworky. Podle Apple (WWDC 2024) přibližně 35 % aplikací v App Store stále obsahuje kód Objective-C.
Klíčová vlastnost — dynamický runtime. Na rozdíl od Swifitu, kde se volání metod řeší ve fázi kompilace, Objective-C odesílá zprávy během běhu pomocí funkce objc_msgSend. To umožňuje přepisovat metody za běhu (method swizzling), dynamicky přidávat třídy a používat forward invocation pro neexistující selektory.
Jakýkoli C kód je v Objective-C správný. Objektová nadstavba přidává třídy (@interface/@implementation), kategorie, protokoly (@protocol) a dynamické typování (id). Soubory mají přípony .m (implementace) a .h (hlavičky).
Syntaxe zpráv — hlavní rozdíl Objective-C od jazyků podobných C. Místo object.method(argument) se používá [object method:argument]. Každá zpráva prochází přes objc_msgSend, který dynamicky hledá implementaci metody v runtime.
// Syntaxe zpráv s pojmenovanými parametry
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// Vnořené zprávy
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// Kontrola typu pomocí introspekce
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}Dynamic dispatch umožňuje přepisovat metody za běhu (method swizzling) — mocná, ale nebezpečná technika. Například frameworky jako AFNetworking a Aspects používají swizzling pro zachycování volání URLSession. Apple varuje: swizzling může při nesprávném použití narušit činnost systémových frameworků.
Categories — jedinečná možnost Objective-C přidávat metody k existujícím třídám (včetně systémových, jako NSString a UIView) bez dědičnosti a bez přístupu ke zdrojovému kódu. Kategorie se deklarují pomocí @interface ClassName (CategoryName).
// Soubor UIColor+Hex.h — kategorie pro UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// Soubor UIColor+Hex.m — implementace
@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];
}
@endExtensions (Class Extension) — zvláštní druh kategorie deklarovaný v .m souboru beze jména: @interface ClassName (). Na rozdíl od kategorií mohou extensions přidávat nejen metody, ale také ivar (proměnné instance) a property. Extensions se používají ke skrytí interního API před externími moduly.
Blocks — anonymní funkce v Objective-C zachytávající proměnné z vnějšího rozsahu viditelnosti. Syntaxe bloků: ^(int x) { return x * 2; }. Blocks se používají v UIKit pro callback handlery, v Grand Central Dispatch pro asynchronní úkoly a v kolekcích NSArray/NSDictionary pro funkcionální operace.
// Deklarace typu bloku
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// Blok jako parametr
- (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);
}
});
}Správa paměti v blocích je kritická. Bloky zachytávají self silnou referencí, což při přímém použití vytváří retain cycle. Řešení — __weak typeof(self) weakSelf = self, s následnou kontrolou uvnitř bloku. Tento problém je zcela vyřešen ve Swiftu pomocí capture list [weak self].
Objective-C prošel cestou od MRC (Manual Reference Counting) k ARC (Automatic Reference Counting). V MRC programátor ručně volal retain (zvýšení čítače), release (snížení) a autorelease (odložené uvolnění). Chyby v těchto voláních vedly k únikům paměti nebo pádům kvůli dangling pointers.
| Operace | MRC | ARC |
|---|---|---|
| Vytvoření objektu | [[Object alloc] init] | [[Object alloc] init] |
| Držení reference | [object retain] | Automaticky |
| Uvolnění | [object release] | Automaticky |
| Automatické uvolnění | [object autorelease] | Automaticky (není vyžadováno) |
| Weak reference | __weak neexistovalo | __weak (automatické nil) |
ARC byl představen v Xcode 4.2 a LLVM 3.0 (2011). Kompilátor automaticky vkládá retain/release ve fázi kompilace na základě analýzy životnosti objektů. ARC není garbage collection — jedná se o statickou analýzu s automatickým vkládáním. Objective-C ARC je kompatibilní se Swift ARC: oba používají stejný systém počítání referencí na úrovni runtime.
Společné používání Objective-C a Swifitu v jednom projektu — běžná praxe u legacy projektů. Apple poskytuje Bridging Header — automaticky generovaný soubor, přes který Swift vidí třídy Objective-C a Objective-C vidí třídy Swifitu zděděné z NSObject.
// ProjectName-Bridging-Header.h
// Swift vidí tyto hlavičky automaticky
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"Migrace z Objective-C na Swift — postupný proces. Nové soubory se píší ve Swiftu, staré se postupně refaktorují. Bridging Header se automaticky vygeneruje při přidání prvního Swift souboru do projektu Objective-C. Pro zpětnou viditelnost (ObjC → Swift) Xcode generuje soubor
// Třída Swift viditelná z Objective-C
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// implementace
}
}Omezení: Swift value typy (struct, enum) nejsou přímo viditelné z Objective-C — je třeba je zabalit do class s @objc. Generics ve Swiftu jsou z Objective-C přístupné omezeně. Doporučený přístup — pište nový kód ve Swiftu a stávající kód Objective-C refaktorujte pouze při změně příslušné funkcionality.
Hlavní výhoda Objective-C oproti Swiftu — plný přístup k runtime. Method swizzling, nahrazování implementací metod za běhu, umožňuje přepisovat systémové metody bez dědičnosti. Knihovny jako Aspects a JRSwizzle používají tuto možnost pro AOP (aspektově orientované programování) — monitorování, analytiku a logování.
Forward invocation — další runtime možnost: pokud objekt nereaguje na selektor, systém zavolá forwardInvocation:, což umožňuje přesměrování zprávy na jiný objekt. To je základ Proxy vzoru v Objective-C (NSProxy), používaného pro odloženou inicializaci a distribuované objekty.
Apple doporučuje minimalizovat používání runtime triků v novém kódu a upřednostňovat statické typování Swifitu. V legacy projektech je však znalost objc_msgSend, method_exchangeImplementations a objc_getAssociatedObject nezbytná pro údržbu stávající kódové základny.
Objective-C podporuje property jako syntaktický cukr nad ivar s gettry/settrými. Modifikátory atomic/nonatomic, strong/weak/copy, readonly/readwrite a assign/retain určují chování paměti a bezpečnost vláken. Key-Value Observing (KVO) — mechanismus sledování změn vlastností zabudovaný do runtime: jakýkoli objekt se může přihlásit ke sledování změn vlastností jiného objektu pomocí addObserver.
Často kladené otázky
Volání metody vypadá jako [object selector:argument]. Zpráva prochází přes objc_msgSend, který dynamicky najde implementaci v runtime. Selektor je název metody (@selector(methodName)), ne ukazatel na funkci. To umožňuje swizzling a forward invocation.
Category (@interface ClassName (Name)) přidává metody k libovolné třídě (včetně systémových) bez dědičnosti. Extension (@interface ClassName ()) se deklaruje v .m souboru a může přidávat property a ivar. Category nemůže přidávat ivar, extension může.
Blocks — anonymní funkce se syntaxí ^(parametry) { tělo }, zachytávající proměnné z kontextu. Obdoba lambd v C++ a closures ve Swiftu. Vyžadují __weak pro zabránění retain cycles při zachycení self. Používají se v UIKit, GCD a Foundation.
MRC — ruční počítání referencí: programátor volá retain, release, autorelease. ARC — automatické: kompilátor vkládá retain/release na základě statické analýzy. ARC není GC — objekty se uvolní okamžitě při vynulování čítače. ARC podporuje modifikátory __weak a __strong.
Ano, pomocí Bridging Header. Swift vidí Objective-C přes tuto hlavičku, Objective-C vidí Swift přes
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také