Objective-C — زبان برنامهنویسی با ارسال پویای پیام که توسط برد کاکس در دهه ۱۹۸۰ ساخته شد. اپل Objective-C را به عنوان زبان اصلی برای NeXTSTEP و سپس برای iOS SDK انتخاب کرد. Programming With Objective-C — معرفی نحو پیام و مدیریت حافظه.
نکات اصلی
Objective-C — زبان برنامهنویسی که C را با قابلیتهای برنامهنویسی شیءگرا به سبک Smalltalk توسعه میدهد. کد Objective-C از طریق LLVM یا GCC به کد ماشین بومی کامپایل میشود و سازگاری کامل معکوس با C را حفظ میکند — هر کد C در Objective-C معتبر است.
اپل NeXT (همراه با Objective-C) را در سال ۱۹۹۷ خریداری کرد. این زبان به پایه Cocoa و Cocoa Touch — چارچوبهای macOS و iOS تبدیل شد. از سال ۲۰۱۴ اپل Swift را به عنوان جایگزین معرفی میکند، اما Objective-C برای پروژههای legacy و برخی چارچوبهای سیستمی حیاتی باقی مانده است. طبق دادههای اپل (WWDC 2024)، حدود ۳۵٪ از برنامههای App Store همچنان حاوی کد Objective-C هستند.
ویژگی کلیدی — runtime پویا. برخلاف Swift که در آن فراخوانی متدها در مرحله کامپایل حل میشوند، Objective-C پیامها را در زمان اجرا از طریق تابع objc_msgSend ارسال میکند. این امکان بازتعریف متدها در لحظه (method swizzling)، افزودن پویای کلاسها و استفاده از forward invocation برای selectorهای ناموجود را فراهم میکند.
هر کد C در Objective-C معتبر است. لایه شیء کلاسها (@interface/@implementation)، دستهبندیها، پروتکلها (@protocol) و تایپبندی پویا (id) را اضافه میکند. فایلها دارای پسوندهای .m (پیادهسازی) و .h (سرآیندها) هستند.
نحو پیام — تفاوت اصلی Objective-C با زبانهای C-مانند. به جای object.method(argument) از [object method:argument] استفاده میشود. هر پیام از objc_msgSend عبور میکند که به طور پویا پیادهسازی متد را در runtime جستجو میکند.
// نحو پیام با پارامترهای نامگذاری شده
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// پیامهای تو در تو
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// بررسی نوع از طریق introspection
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}Dynamic dispatch امکان بازتعریف متدها در runtime (method swizzling) را فراهم میکند — تکنیکی قدرتمند اما خطرناک. به عنوان مثال، چارچوبهایی مانند AFNetworking و Aspects از swizzling برای رهگیری فراخوانیهای URLSession استفاده میکنند. اپل هشدار میدهد: swizzling در صورت استفاده نادرست میتواند عملکرد چارچوبهای سیستمی را مختل کند.
Categories — امکان منحصربهفرد Objective-C برای افزودن متد به کلاسهای موجود (از جمله سیستمی، مانند NSString و UIView) بدون وراثت و بدون دسترسی به کد منبع. دستهبندیها از طریق @interface ClassName (CategoryName) اعلام میشوند.
// فایل UIColor+Hex.h — دستهبندی برای UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// فایل UIColor+Hex.m — پیادهسازی
@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) — نوع خاصی از دستهبندی که در فایل .m بدون نام اعلام میشود: @interface ClassName (). برخلاف دستهبندیها، extensions میتوانند نه تنها متدها، بلکه ivar (متغیرهای نمونه) و property را نیز اضافه کنند. Extensions برای پنهان کردن API داخلی از ماژولهای خارجی استفاده میشوند.
Blocks — توابع ناشناس در Objective-C که متغیرها را از محدوده دید خارجی میگیرند. نحو بلوکها: ^(int x) { return x * 2; }. Blocks در UIKit برای handlerهای callback، در Grand Central Dispatch برای وظایف ناهمگام و در مجموعههای NSArray/NSDictionary برای عملیات تابعی استفاده میشوند.
// اعلام نوع بلوک
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// بلوک به عنوان پارامتر
- (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);
}
});
}مدیریت حافظه در بلوکها حیاتی است. بلوکها self را با مرجع قوی میگیرند که در استفاده مستقیم retain cycle ایجاد میکند. راهحل — __weak typeof(self) weakSelf = self، با بررسی بعدی در داخل بلوک. این مشکل در Swift از طریق لیستهای capture [weak self] کاملاً حل شده است.
Objective-C مسیری از MRC (Manual Reference Counting) تا ARC (Automatic Reference Counting) را طی کرده است. در MRC برنامهنویس به صورت دستی retain (افزایش شمارنده)، release (کاهش) و autorelease (release با تأخیر) را فراخوانی میکرد. خطا در این فراخوانیها منجر به نشت حافظه یا crash به دلیل dangling pointers میشد.
| عملیات | MRC | ARC |
|---|---|---|
| ایجاد شیء | [[Object alloc] init] | [[Object alloc] init] |
| نگهداری مرجع | [object retain] | خودکار |
| آزادسازی | [object release] | خودکار |
| آزادسازی خودکار | [object autorelease] | خودکار (نیاز نیست) |
| مرجع Weak | __weak وجود نداشت | __weak (nil خودکار) |
ARC در Xcode 4.2 و LLVM 3.0 (2011) معرفی شد. کامپایلر به طور خودکار retain/release را در مرحله کامپایل با تحلیل طول عمر اشیاء درج میکند. ARC جمعآوری زباله (garbage collection) نیست — این تحلیل استاتیک با درجهای خودکار است. Objective-C ARC با Swift ARC سازگار است: هر دو از یک سیستم شمارش مرجع در سطح runtime استفاده میکنند.
استفاده مشترک از Objective-C و Swift در یک پروژه — رویه معمول برای پروژههای legacy. اپل Bridging Header را ارائه میدهد — فایلی که به طور خودکار تولید میشود و از طریق آن Swift کلاسهای Objective-C را میبیند و Objective-C کلاسهای Swift را که از NSObject ارث بردهاند میبیند.
// ProjectName-Bridging-Header.h
// Swift این سرآیندها را به طور خودکار میبیند
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"مهاجرت از Objective-C به Swift — فرآیندی مرحلهای. فایلهای جدید به Swift نوشته میشوند، فایلهای قدیمی به تدریج بازنویسی میشوند. Bridging Header به طور خودکار هنگام افزودن اولین فایل Swift به پروژه Objective-C تولید میشود. برای دید معکوس (ObjC → Swift) Xcode فایل
// کلاس Swift قابل مشاهده از Objective-C
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// پیادهسازی
}
}محدودیتها: انواع value Swift (struct, enum) مستقیماً از Objective-C قابل مشاهده نیستند — باید آنها را در class با @objc بپیچید. Generics در Swift به صورت محدود از Objective-C در دسترس است. رویکرد توصیهشده — نوشتن کد جدید به Swift و بازنویسی کد Objective-C موجود فقط هنگام تغییر قابلیت مربوطه.
مزیت اصلی Objective-C نسبت به Swift — دسترسی کامل به runtime. Method swizzling، جایگزینی پیادهسازی متدها در زمان اجرا، امکان بازتعریف متدهای سیستمی بدون وراثت را فراهم میکند. کتابخانههایی مانند Aspects و JRSwizzle از این امکان برای AOP (برنامهنویسی جنبهگرا) — پایش، تحلیل و لاگگیری استفاده میکنند.
Forward invocation — یکی دیگر از قابلیتهای runtime: اگر شیء به selector پاسخ ندهد، سیستم forwardInvocation: را فراخوانی میکند و امکان هدایت پیام به شیء دیگر را فراهم میکند. این اساس الگوی Proxy در Objective-C (NSProxy) است که برای مقداردهی تأخیری و اشیاء توزیعشده استفاده میشود.
اپل توصیه میکند استفاده از ترفندهای runtime را در کد جدید به حداقل برسانید و به تایپبندی استاتیک Swift اولویت دهید. با این حال، در پروژههای legacy آشنایی با objc_msgSend، method_exchangeImplementations و objc_getAssociatedObject برای پشتیبانی از پایگاه کد موجود ضروری است.
Objective-C از property به عنوان شکر نحوی روی ivar با getter/setter پشتیبانی میکند. اصلاحکنندههای atomic/nonatomic، strong/weak/copy، readonly/readwrite و assign/retain رفتار حافظه و ایمنی نخ را تعیین میکنند. Key-Value Observing (KVO) — سازوکار مشاهده تغییرات خصوصیات تعبیهشده در runtime: هر شیء میتواند از طریق addObserver تغییرات خصوصیات شیء دیگر را دنبال کند.
سوالات متداول
فراخوانی متد به صورت [object selector:argument] است. پیام از objc_msgSend عبور میکند که به طور پویا پیادهسازی را در runtime پیدا میکند. selector نام متد است (@selector(methodName))، نه اشارهگر به تابع. این امکان swizzling و forward invocation را فراهم میکند.
Category (@interface ClassName (Name)) متدها را به هر کلاسی (از جمله سیستمی) بدون وراثت اضافه میکند. Extension (@interface ClassName ()) در فایل .m اعلام میشود و میتواند property و ivar اضافه کند. Category نمیتواند ivar اضافه کند، extension میتواند.
Blocks — توابع ناشناس با نحو ^(پارامترها) { بدنه } که متغیرها را از زمینه میگیرند. مشابه لامبداها در C++ و closures در Swift. برای جلوگیری از retain cycles هنگام گرفتن self نیاز به __weak دارند. در UIKit، GCD و Foundation استفاده میشوند.
MRC — شمارش مرجع دستی: برنامهنویس retain، release، autorelease را فراخوانی میکند. ARC — خودکار: کامپایلر retain/release را بر اساس تحلیل استاتیک درج میکند. ARC GC نیست — اشیاء بلافاصله پس از صفر شدن شمارنده آزاد میشوند. ARC از اصلاحکنندههای __weak و __strong پشتیبانی میکند.
بله، از طریق Bridging Header. Swift Objective-C را از طریق این سرآیند میبیند، Objective-C Swift را از طریق
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.