Objective-C ist eine Programmiersprache mit dynamischem Nachrichtenversand, die in den 1980er Jahren von Brad Cox entwickelt wurde. Apple wählte Objective-C als primäre Sprache für NeXTSTEP und später für das iOS SDK. Programming With Objective-C — eine Einführung in die Nachrichtensyntax und Speicherverwaltung.
Wichtige Erkenntnisse
Objective-C ist eine Programmiersprache, die C um objektorientierte Programmierfähigkeiten im Smalltalk-Stil erweitert. Objective-C-Code wird über LLVM oder GCC in nativen Maschinencode kompiliert und behält die vollständige Abwärtskompatibilität mit C bei — jeder C-Code ist in Objective-C gültig.
Apple übernahm NeXT (zusammen mit Objective-C) im Jahr 1997. Die Sprache wurde zur Grundlage von Cocoa und Cocoa Touch — den Frameworks für macOS und iOS. Seit 2014 bewirbt Apple Swift als Ersatz, aber Objective-C bleibt für Legacy-Projekte und einige System-Frameworks kritisch wichtig. Laut Apple (WWDC 2024) enthalten etwa 35 % der Apps im App Store noch Objective-C-Code.
Das Hauptmerkmal ist die dynamische Laufzeitumgebung. Im Gegensatz zu Swift, wo Methodenaufrufe zur Kompilierzeit aufgelöst werden, sendet Objective-C Nachrichten zur Laufzeit über die Funktion objc_msgSend. Dies ermöglicht das Überschreiben von Methoden im laufenden Betrieb (Method Swizzling), das dynamische Hinzufügen von Klassen und die Verwendung von Forward Invocation für nicht existierende Selektoren.
Jeder C-Code ist in Objective-C gültig. Die objektorientierte Erweiterung fügt Klassen (@interface/@implementation), Kategorien, Protokolle (@protocol) und dynamische Typisierung (id) hinzu. Dateien haben die Erweiterungen .m (Implementierung) und .h (Header).
Die Nachrichtensyntax ist der Hauptunterschied zwischen Objective-C und C-ähnlichen Sprachen. Anstelle von object.method(argument) wird [object method:argument] verwendet. Jede Nachricht durchläuft objc_msgSend, das dynamisch die Methodenimplementierung zur Laufzeit sucht.
// Nachrichtensyntax mit benannten Parametern
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// Verschachtelte Nachrichten
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// Typüberprüfung durch Introspection
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}Dynamischer Dispatch ermöglicht das Überschreiben von Methoden zur Laufzeit (Method Swizzling) — eine mächtige, aber gefährliche Technik. Frameworks wie AFNetworking und Aspects verwenden Swizzling, um URLSession-Aufrufe abzufangen. Apple warnt: Swizzling kann System-Frameworks beschädigen, wenn es falsch verwendet wird.
Kategorien sind eine einzigartige Funktion von Objective-C, die das Hinzufügen von Methoden zu vorhandenen Klassen (einschließlich Systemklassen wie NSString und UIView) ohne Vererbung und ohne Zugriff auf den Quellcode ermöglicht. Kategorien werden über @interface ClassName (CategoryName) deklariert.
// UIColor+Hex.h-Datei — Kategorie für UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// UIColor+Hex.m-Datei — Implementierung
@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];
}
@endErweiterungen (Class Extension) sind eine spezielle Art von Kategorie, die in einer .m-Datei ohne Namen deklariert wird: @interface ClassName (). Im Gegensatz zu Kategorien können Erweiterungen nicht nur Methoden, sondern auch ivar (Instanzvariablen) und Eigenschaften hinzufügen. Erweiterungen werden verwendet, um die interne API vor externen Modulen zu verbergen.
Blöcke sind anonyme Funktionen in Objective-C, die Variablen aus dem äußeren Gültigkeitsbereich erfassen. Blocksyntax: ^(int x) { return x * 2; }. Blöcke werden in UIKit für Callback-Handler, in Grand Central Dispatch für asynchrone Aufgaben und in NSArray/NSDictionary-Sammlungen für funktionale Operationen verwendet.
// Blocktyp-Deklaration
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// Block als Parameter
- (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);
}
});
}Die Speicherverwaltung in Blöcken ist kritisch wichtig. Blöcke erfassen self mit einer starken Referenz, was bei direkter Verwendung einen Retain-Cycle erzeugt. Die Lösung ist __weak typeof(self) weakSelf = self, gefolgt von einer Überprüfung innerhalb des Blocks. Dieses Problem ist in Swift durch Capture Lists [weak self] vollständig gelöst.
Objective-C entwickelte sich von MRC (Manual Reference Counting) zu ARC (Automatic Reference Counting). In MRC rief der Entwickler manuell retain (Zähler erhöhen), release (verringern) und autorelease (verzögerte Freigabe) auf. Fehler in diesen Aufrufen führten zu Speicherlecks oder Abstürzen aufgrund von baumelnden Zeigern.
| Operation | MRC | ARC |
|---|---|---|
| Objekterstellung | [[Object alloc] init] | [[Object alloc] init] |
| Referenzhalten | [object retain] | Automatisch |
| Freigabe | [object release] | Automatisch |
| Autofreigabe | [object autorelease] | Automatisch (nicht erforderlich) |
| Schwache Referenz | __weak existierte nicht | __weak (automatisches nil) |
ARC wurde in Xcode 4.2 und LLVM 3.0 (2011) eingeführt. Der Compiler fügt zur Kompilierzeit automatisch retain/release ein, indem er die Lebensdauer von Objekten analysiert. ARC ist keine Garbage Collection — es ist eine statische Analyse mit automatischen Einfügungen. Objective-C ARC ist mit Swift ARC kompatibel: beide verwenden dasselbe Referenzzählsystem auf Runtime-Ebene.
Die gemeinsame Verwendung von Objective-C und Swift in einem Projekt ist bei Legacy-Projekten üblich. Apple stellt den Bridging Header bereit — eine automatisch generierte Datei, durch die Swift Objective-C-Klassen sieht und Objective-C Swift-Klassen sieht, die von NSObject erben.
// ProjectName-Bridging-Header.h
// Swift sieht diese Header automatisch
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"Migration von Objective-C zu Swift ist ein schrittweiser Prozess. Neue Dateien werden in Swift geschrieben, alte werden nach und nach refaktoriert. Der Bridging Header wird automatisch generiert, wenn die erste Swift-Datei zu einem Objective-C-Projekt hinzugefügt wird. Für die umgekehrte Sichtbarkeit (ObjC → Swift) generiert Xcode eine <ProjectName>-Swift.h-Datei mit @interface-Deklarationen für Swift-Klassen, die mit @objc markiert sind.
// Von Objective-C sichtbare Swift-Klasse
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// Implementierung
}
}Einschränkungen: Swift-Wertetypen (struct, enum) sind von Objective-C nicht direkt sichtbar — sie müssen in eine Klasse mit @objc eingewickelt werden. Swift-Generics sind von Objective-C aus eingeschränkt zugänglich. Der empfohlene Ansatz ist, neuen Code in Swift zu schreiben und vorhandenen Objective-C-Code nur bei Änderung der entsprechenden Funktionalität zu refaktorieren.
Der Hauptvorteil von Objective-C gegenüber Swift ist der vollständige Zugriff auf die Laufzeitumgebung. Method Swizzling, das Ersetzen von Methodenimplementierungen zur Laufzeit, ermöglicht das Überschreiben von Systemmethoden ohne Vererbung. Bibliotheken wie Aspects und JRSwizzle nutzen diese Fähigkeit für AOP (aspektorientierte Programmierung) — Überwachung, Analyse und Protokollierung.
Forward Invocation ist eine weitere Runtime-Funktion: Wenn ein Objekt nicht auf einen Selektor reagiert, ruft das System forwardInvocation: auf, wodurch die Nachricht an ein anderes Objekt weitergeleitet werden kann. Dies ist die Grundlage des Proxy-Musters in Objective-C (NSProxy), das für verzögerte Initialisierung und verteilte Objekte verwendet wird.
Apple empfiehlt, Runtime-Tricks in neuem Code zu minimieren und Swifts statische Typisierung zu bevorzugen. In Legacy-Projekten sind jedoch Kenntnisse von objc_msgSend, method_exchangeImplementations und objc_getAssociatedObject für die Wartung der vorhandenen Codebasis erforderlich.
Objective-C unterstützt Properties als syntaktischen Zucker über ivar mit Gettern/Settern. Die Modifikatoren atomic/nonatomic, strong/weak/copy, readonly/readwrite und assign/retain bestimmen das Speicherverhalten und die Threadsicherheit. Key-Value Observing (KVO) ist ein in die Laufzeitumgebung integrierter Mechanismus zur Beobachtung von Eigenschaftsänderungen: Jedes Objekt kann Änderungen der Eigenschaften eines anderen Objekts über addObserver abonnieren.
Häufig gestellte Fragen
Ein Methodenaufruf sieht aus wie [object selector:argument]. Die Nachricht durchläuft objc_msgSend, das dynamisch die Implementierung in der Laufzeitumgebung findet. Ein Selektor ist ein Methodenname (@selector(methodName)), kein Funktionszeiger. Dies ermöglicht Swizzling und Forward Invocation.
Eine Kategorie (@interface ClassName (Name)) fügt Methoden zu jeder Klasse (einschließlich Systemklassen) ohne Vererbung hinzu. Eine Erweiterung (@interface ClassName ()) wird in einer .m-Datei deklariert und kann Eigenschaften und ivars hinzufügen. Eine Kategorie kann keine ivars hinzufügen, eine Erweiterung jedoch schon.
Blöcke sind anonyme Funktionen mit der Syntax ^(Parameter) { Körper }, die Variablen aus dem Kontext erfassen. Sie sind analog zu Lambdas in C++ und Closures in Swift. Sie erfordern __weak, um Retain-Cycles beim Erfassen von self zu verhindern. Sie werden in UIKit, GCD und Foundation verwendet.
MRC ist manuelle Referenzzählung: Der Programmierer ruft retain, release, autorelease auf. ARC ist automatisch: Der Compiler fügt retain/release basierend auf statischer Analyse ein. ARC ist kein GC — Objekte werden sofort freigegeben, wenn der Zähler Null erreicht. ARC unterstützt die Modifikatoren __weak und __strong.
Ja, über einen Bridging Header. Swift sieht Objective-C durch diesen Header, Objective-C sieht Swift durch <ProjectName>-Swift.h. Swift-Klassen müssen von NSObject erben und mit @objc markiert sein. Structs und Enums von Swift sind für Objective-C nicht direkt sichtbar.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch