Objective-C, 1980'lerde Brad Cox tarafından oluşturulan, dinamik mesaj dağıtımına sahip bir programlama dilidir. Apple, NeXTSTEP için ve daha sonra iOS SDK için birincil dil olarak Objective-C'yi seçti. Programming With Objective-C — mesaj sözdizimi ve bellek yönetimine giriş.
\nÖnemli Noktalar
\nObjective-C, C'yi Smalltalk tarzında nesne yönelimli programlama yetenekleriyle genişleten bir programlama dilidir. Objective-C kodu, LLVM veya GCC aracılığıyla yerel makine koduna derlenir ve C ile tam geriye dönük uyumluluğu korur — herhangi bir C kodu Objective-C'de geçerlidir.
\nApple, 1997'de NeXT'yi (Objective-C ile birlikte) satın aldı. Dil, macOS ve iOS için framework'ler olan Cocoa ve Cocoa Touch'ın temeli oldu. 2014'ten bu yana Apple, Swift'i bir yedek olarak tanıtıyor, ancak Objective-C, eski projeler ve bazı sistem framework'leri için kritik derecede önemli olmaya devam ediyor. Apple'a (WWDC 2024) göre, App Store'daki uygulamaların yaklaşık %35'i hala Objective-C kodu içeriyor.
\nTemel özellik dinamik çalışma zamanıdır. Yöntem çağrılarının derleme zamanında çözüldüğü Swift'in aksine, Objective-C, objc_msgSend işlevi aracılığıyla çalışma zamanında mesajlar gönderir. Bu, yöntemleri anında geçersiz kılmaya (method swizzling), dinamik olarak sınıf eklemeye ve var olmayan seçiciler için forward invocation kullanmaya olanak tanır.
\nHerhangi bir C kodu Objective-C'de geçerlidir. Nesne yönelimli uzantı, sınıflar (@interface/@implementation), kategoriler, protokoller (@protocol) ve dinamik tipleme (id) ekler. Dosyalar .m (uygulama) ve .h (başlık) uzantılarına sahiptir.
\nMesaj sözdizimi, Objective-C ile C benzeri diller arasındaki temel farktır. object.method(argument) yerine [object method:argument] kullanılır. Her mesaj, çalışma zamanında dinamik olarak yöntem uygulamasını arayan objc_msgSend'den geçer.
\n// Adlandırılmış parametrelerle mesaj sözdizimi
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// İç içe mesajlar
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// Introspection ile tür denetimi
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}Dinamik dağıtım, çalışma zamanında yöntemleri geçersiz kılmaya (method swizzling) olanak tanır — güçlü ancak tehlikeli bir teknik. Örneğin, AFNetworking ve Aspects gibi framework'ler, URLSession çağrılarını engellemek için swizzling kullanır. Apple uyarıyor: yanlış kullanıldığında swizzling, sistem framework'lerini bozabilir.
\nKategoriler, kalıtım ve kaynak koduna erişim olmadan mevcut sınıflara (NSString ve UIView gibi sistem sınıfları dahil) yöntem eklemeye izin veren Objective-C'nin benzersiz bir özelliğidir. Kategoriler @interface ClassName (CategoryName) aracılığıyla bildirilir.
\n// UIColor+Hex.h dosyası — UIColor için kategori
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// UIColor+Hex.m dosyası — uygulama
@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];
}
@endUzantılar (Class Extension), bir .m dosyasında adsız olarak bildirilen özel bir kategori türüdür: @interface ClassName (). Kategorilerin aksine, uzantılar yalnızca yöntemleri değil, aynı zamanda ivar (örnek değişkenleri) ve özellikleri de ekleyebilir. Uzantılar, dahili API'yi harici modüllerden gizlemek için kullanılır.
\nBloklar, dış kapsamdaki değişkenleri yakalayan Objective-C'deki anonim işlevlerdir. Blok sözdizimi: ^(int x) { return x * 2; }. Bloklar, UIKit'te geri çağırma işleyicileri için, Grand Central Dispatch'te asenkron görevler için ve NSArray/NSDictionary koleksiyonlarında işlevsel işlemler için kullanılır.
\n// Blok türü bildirimi
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// Parametre olarak blok
- (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);
}
});
}Bloklarda bellek yönetimi kritik derecede önemlidir. Bloklar, self'i güçlü bir referansla yakalar ve doğrudan kullanıldığında retain cycle oluşturur. Çözüm, __weak typeof(self) weakSelf = self ve ardından blok içinde bir kontroldür. Bu sorun Swift'te capture lists [weak self] aracılığıyla tamamen çözülmüştür.
\nObjective-C, MRC (Manual Reference Counting)'den ARC (Automatic Reference Counting)'ye evrilmiştir. MRC'de, geliştirici manuel olarak retain (arttırma), release (azaltma) ve autorelease (ertelenmiş serbest bırakma) çağrısı yapardı. Bu çağrılardaki hatalar, sarkan işaretçiler nedeniyle bellek sızıntılarına veya çökmelere yol açardı.
\n| İşlem | MRC | ARC |
|---|---|---|
| Nesne oluşturma | [[Object alloc] init] | [[Object alloc] init] |
| Referans tutma | [object retain] | Otomatik |
| Serbest bırakma | [object release] | Otomatik |
| Otomatik serbest bırakma | [object autorelease] | Otomatik (gerekli değil) |
| Zayıf referans | __weak mevcut değildi | __weak (otomatik nil) |
ARC, Xcode 4.2 ve LLVM 3.0'da (2011) tanıtıldı. Derleyici, nesne ömürlerini analiz ederek derleme zamanında otomatik olarak retain/release ekler. ARC çöp toplama (GC) değildir — otomatik eklemelerle statik analizdir. Objective-C ARC, Swift ARC ile uyumludur: her ikisi de çalışma zamanı düzeyinde aynı referans sayma sistemini kullanır.
\nBir projede Objective-C ve Swift'i birlikte kullanmak, eski projeler için yaygın bir uygulamadır. Apple, Bridging Header'ı sağlar — Swift'in Objective-C sınıflarını gördüğü ve Objective-C'nin NSObject'ten miras alan Swift sınıflarını gördüğü otomatik olarak oluşturulan bir dosya.
\n// ProjectName-Bridging-Header.h
// Swift bu başlıkları otomatik olarak görür
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"Objective-C'den Swift'e geçiş aşamalı bir süreçtir. Yeni dosyalar Swift'te yazılır, eskileri kademeli olarak yeniden düzenlenir. Bridging Header, bir Objective-C projesine ilk Swift dosyası eklendiğinde otomatik olarak oluşturulur. Ters görünürlük için (ObjC → Swift), Xcode, @objc ile işaretlenmiş Swift sınıfları için @interface bildirimleri içeren bir <ProjectName>-Swift.h dosyası oluşturur.
\n// Objective-C'den görünen Swift sınıfı
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// uygulama
}
}Sınırlamalar: Swift'in değer türleri (struct, enum) Objective-C'den doğrudan görünmez — @objc ile bir sınıfa sarılmaları gerekir. Swift'in jenerikleri Objective-C'den sınırlı olarak erişilebilir. Önerilen yaklaşım, yeni kodu Swift'te yazmak ve mevcut Objective-C kodunu yalnızca ilgili işlevsellik değiştirildiğinde yeniden düzenlemektir.
\nSwift'e kıyasla Objective-C'nin ana avantajı, çalışma zamanına tam erişimdir. Method swizzling, çalışma zamanında yöntem uygulamalarını değiştirme, kalıtım olmadan sistem yöntemlerini geçersiz kılmaya olanak tanır. Aspects ve JRSwizzle gibi kütüphaneler, bu yeteneği AOP (yönelim odaklı programlama) — izleme, analitik ve günlükleme için kullanır.
\nForward invocation, başka bir çalışma zamanı özelliğidir: bir nesne bir seçiciye yanıt vermezse, sistem forwardInvocation:'ı çağırır ve mesajın başka bir nesneye iletilmesine olanak tanır. Bu, Objective-C'deki (NSProxy) Proxy deseninin temelidir ve tembel başlatma ve dağıtılmış nesneler için kullanılır.
\nApple, yeni kodda çalışma zamanı hilelerinin kullanımını en aza indirmeyi ve Swift'in statik tiplemesini tercih etmeyi önerir. Ancak, eski projelerde, objc_msgSend, method_exchangeImplementations ve objc_getAssociatedObject bilgisi, mevcut kod tabanının bakımı için gereklidir.
\nObjective-C, getter/setter ile ivar üzerinde özellikleri sözdizimsel şeker olarak destekler. atomic/nonatomic, strong/weak/copy, readonly/readwrite ve assign/retain değiştiricileri, bellek davranışını ve iş parçacığı güvenliğini belirler. Key-Value Observing (KVO), çalışma zamanına yerleşik bir özellik değişikliği gözlem mekanizmasıdır: herhangi bir nesne, addObserver aracılığıyla başka bir nesnenin özelliklerindeki değişikliklere abone olabilir.
\nSıkça Sorulan Sorular
\nBir yöntem çağrısı [object selector:argument] şeklinde görünür. Mesaj, çalışma zamanında dinamik olarak uygulamayı bulan objc_msgSend'den geçer. Seçici, bir yöntem adıdır (@selector(methodName)), bir işlev işaretçisi değil. Bu, swizzling ve forward invocation'a olanak tanır.
Bir Kategori (@interface ClassName (Name)), kalıtım olmadan herhangi bir sınıfa (sistem sınıfları dahil) yöntem ekler. Bir Uzantı (@interface ClassName ()) bir .m dosyasında bildirilir ve özellikler ve ivars ekleyebilir. Bir Kategori ivars ekleyemez, ancak bir Uzantı ekleyebilir.
Bloklar, ^(parametreler) { gövde } sözdizimine sahip, bağlamdan değişkenleri yakalayan anonim işlevlerdir. C++'daki lambda'lara ve Swift'deki kapanışlara benzerler. self'i yakalarken retain cycle'ları önlemek için __weak gerektirirler. UIKit, GCD ve Foundation'da kullanılırlar.
MRC manuel referans sayımıdır: programcı retain, release, autorelease çağırır. ARC otomatiktir: derleyici, statik analize dayalı olarak retain/release ekler. ARC GC değildir — sayaç sıfıra ulaştığında nesneler hemen serbest bırakılır. ARC, __weak ve __strong değiştiricilerini destekler.
Evet, bir Bridging Header aracılığıyla. Swift bu başlık aracılığıyla Objective-C'yi görür, Objective-C <ProjectName>-Swift.h aracılığıyla Swift'i görür. Swift sınıfları NSObject'ten miras almalı ve @objc ile işaretlenmelidir. Swift'in struct ve enum'ları Objective-C tarafından doğrudan görülmez.
Özet
\nAnahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.