Objective-C — ett programmeringsspråk med dynamisk meddelandedirigering, skapat av Brad Cox på 1980-talet. Apple valde Objective-C som huvudspråk för NeXTSTEP och senare för iOS SDK. Programming With Objective-C — introduktion till meddelandesyntax och minneshantering.
Huvudpunkter
Objective-C — ett programmeringsspråk som utökar C med objektorienterade programmeringsmöjligheter i Smalltalk-stil. Kod i Objective-C kompileras via LLVM eller GCC till maskinkod och behåller full bakåtkompatibilitet med C — all C-kod är giltig i Objective-C.
Apple förvärvade NeXT (tillsammans med Objective-C) 1997. Språket blev grunden för Cocoa och Cocoa Touch — ramverken för macOS och iOS. Sedan 2014 marknadsför Apple Swift som ersättning, men Objective-C förblir kritiskt för legacy-projekt och vissa systemramverk. Enligt Apple (WWDC 2024) innehåller cirka 35 % av apparna i App Store fortfarande Objective-C-kod.
Nyckelfunktion — dynamisk runtime. Till skillnad från Swift, där metodanrop löses vid kompilering, skickar Objective-C meddelanden under exekvering via funktionen objc_msgSend. Detta gör det möjligt att åsidosätta metoder i farten (method swizzling), dynamiskt lägga till klasser och använda forward invocation för icke-existerande selektorer.
All C-kod är giltig i Objective-C. Objektlagret lägger till klasser (@interface/@implementation), kategorier, protokoll (@protocol) och dynamisk typning (id). Filer har tilläggen .m (implementering) och .h (rubriker).
Meddelandesyntax — den huvudsakliga skillnaden mellan Objective-C och C-liknande språk. Istället för object.method(argument) används [object method:argument]. Varje meddelande går igenom objc_msgSend, som dynamiskt söker efter metodens implementering i runtime.
// Meddelandesyntax med namngivna parametrar
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// Nästlade meddelanden
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// Typkontroll via introspektion
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}Dynamic dispatch gör det möjligt att åsidosätta metoder i runtime (method swizzling) — en kraftfull men farlig teknik. Ramverk som AFNetworking och Aspects använder swizzling för att fånga upp URLSession-anrop. Apple varnar: swizzling kan störa systemramverkens funktion vid felaktig användning.
Categories — en unik möjlighet i Objective-C att lägga till metoder till befintliga klasser (inklusive systemklasser som NSString och UIView) utan arv och utan tillgång till källkod. Kategorier deklareras via @interface ClassName (CategoryName).
// Fil UIColor+Hex.h — kategori för UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// Fil UIColor+Hex.m — implementering
@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) — en speciell typ av kategori, deklarerad i .m-fil utan namn: @interface ClassName (). Till skillnad från kategorier kan extensions lägga till inte bara metoder, utan även ivar (instansvariabler) och property. Extensions används för att dölja internt API från externa moduler.
Blocks — anonyma funktioner i Objective-C som fångar variabler från det yttre omfånget. Blocksyntax: ^(int x) { return x * 2; }. Blocks används i UIKit för callback-hanterare, i Grand Central Dispatch för asynkrona uppgifter och i NSArray/NSDictionary-samlingar för funktionella operationer.
// Deklaration av blocktyp
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// Block som 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);
}
});
}Minneshantering i block är kritisk. Block fångar self med en stark referens, vilket skapar en retain cycle vid direkt användning. Lösning — __weak typeof(self) weakSelf = self, med efterföljande kontroll inuti blocket. Detta problem är helt löst i Swift genom capture lists [weak self].
Objective-C har gått från MRC (Manual Reference Counting) till ARC (Automatic Reference Counting). I MRC anropade programmeraren manuellt retain (öka räknaren), release (minska) och autorelease (fördröjd frigöring). Fel i dessa anrop ledde till minnesläckor eller krascher på grund av hängande pekare.
| Operation | MRC | ARC |
|---|---|---|
| Skapa objekt | [[Object alloc] init] | [[Object alloc] init] |
| Behålla referens | [object retain] | Automatiskt |
| Frigöring | [object release] | Automatiskt |
| Automatisk frigöring | [object autorelease] | Automatiskt (krävs inte) |
| Weak referens | __weak fanns inte | __weak (automatisk nil) |
ARC introducerades i Xcode 4.2 och LLVM 3.0 (2011). Kompilatorn infogar automatiskt retain/release vid kompilering genom att analysera objektens livslängd. ARC är inte garbage collection — det är statisk analys med automatiska insättningar. Objective-C ARC är kompatibel med Swift ARC: båda använder samma referensräkningssystem på runtime-nivå.
Gemensam användning av Objective-C och Swift i ett projekt — vanlig praxis för legacy-projekt. Apple tillhandahåller Bridging Header — en automatiskt genererad fil genom vilken Swift ser Objective-C-klasser och Objective-C ser Swift-klasser som ärver från NSObject.
// ProjectName-Bridging-Header.h
// Swift ser dessa rubriker automatiskt
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"Migrering från Objective-C till Swift — en stegvis process. Nya filer skrivs i Swift, gamla refaktoreras gradvis. Bridging Header genereras automatiskt när den första Swift-filen läggs till i ett Objective-C-projekt. För omvänd synlighet (ObjC → Swift) genererar Xcode filen
// Swift-klass synlig från Objective-C
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// implementering
}
}Begränsningar: Swift värdetyper (struct, enum) är inte direkt synliga från Objective-C — de måste omslutas i class med @objc. Generics i Swift är begränsat tillgängliga från Objective-C. Rekommenderad metod — skriv ny kod i Swift och refaktorera befintlig Objective-C-kod endast när motsvarande funktionalitet ändras.
Den främsta fördelen med Objective-C jämfört med Swift — full tillgång till runtime. Method swizzling, utbyte av metodimplementeringar under exekvering, gör det möjligt att åsidosätta systemmetoder utan arv. Bibliotek som Aspects och JRSwizzle använder denna funktion för AOP (aspektorienterad programmering) — övervakning, analys och loggning.
Forward invocation — ytterligare en runtime-funktion: om ett objekt inte svarar på en selector anropar systemet forwardInvocation:, vilket möjliggör omdirigering av meddelandet till ett annat objekt. Detta är grunden för Proxy-mönstret i Objective-C (NSProxy), som används för fördröjd initiering och distribuerade objekt.
Apple rekommenderar att minimera användningen av runtime-tricks i ny kod och föredrar Swifts statiska typning. Men i legacy-projekt är kunskap om objc_msgSend, method_exchangeImplementations och objc_getAssociatedObject nödvändig för att underhålla den befintliga kodbasen.
Objective-C stöder property som syntaktisk socker ovanpå ivar med getters/setters. Modifierarna atomic/nonatomic, strong/weak/copy, readonly/readwrite och assign/retain bestämmer minnesbeteende och trådsäkerhet. Key-Value Observing (KVO) — en mekanism för att observera egenskapsändringar inbyggd i runtime: vilket objekt som helst kan prenumerera på ändringar av ett annat objekts egenskaper via addObserver.
Vanliga frågor
Ett metodanrop ser ut som [object selector:argument]. Meddelandet går igenom objc_msgSend, som dynamiskt hittar implementeringen i runtime. En selector är metodens namn (@selector(methodName)), inte en funktionspekare. Detta möjliggör swizzling och forward invocation.
Category (@interface ClassName (Name)) lägger till metoder till vilken klass som helst (inklusive systemklasser) utan arv. Extension (@interface ClassName ()) deklareras i .m-fil och kan lägga till property och ivar. Category kan inte lägga till ivar, extension kan.
Blocks — anonyma funktioner med syntax ^(parametrar) { kropp }, som fångar variabler från kontext. Motsvarighet till lambdas i C++ och closures i Swift. Kräver __weak för att förhindra retain cycles vid infångning av self. Används i UIKit, GCD och Foundation.
MRC — manuell referensräkning: programmeraren anropar retain, release, autorelease. ARC — automatisk: kompilatorn infogar retain/release baserat på statisk analys. ARC är inte GC — objekt frigörs omedelbart när räknaren nollställs. ARC stöder __weak och __strong-modifierare.
Ja, via Bridging Header. Swift ser Objective-C genom denna rubrik, Objective-C ser Swift genom
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också