Objective-C: جوهر اللغة ومكانتها في تطوير iOS

المؤلف: IT Sectr نُشر: 2026-02-09 وقت القراءة: 8 دق

Objective-C هي لغة برمجة مع إرسال ديناميكي للرسائل، أنشأها براد كوكس في الثمانينيات. اختارت Apple لغة Objective-C كلغة رئيسية لـ NeXTSTEP، ثم لاحقًا لـ iOS SDK. Programming With Objective-C — مقدمة إلى صيغة الرسائل وإدارة الذاكرة.

الخلاصة

  • Objective-C — مجموعة شاملة صارمة من C مع صيغة رسائل بين قوسين مربعين وبيئة تشغيل ديناميكية
  • Message passing — استدعاءات الدوال عبر [object selector:argument] مع بحث ديناميكي عن التنفيذ عبر objc_msgSend
  • Categories — آلية لإضافة دوال إلى الفئات الموجودة دون وراثة ودون الوصول إلى الكود المصدري
  • Blocks — دوال مجهولة مع إغلاقات، سابقة لإغلاقات Swift
  • ARC vs MRC — العد التلقائي واليدوي للمراجع لإدارة الذاكرة

ما هو Objective-C؟

Objective-C هي لغة برمجة توسع C بإمكانيات البرمجة كائنية التوجه بأسلوب Smalltalk. يتم تجميع كود Objective-C عبر LLVM أو GCC إلى كود آلة أصلي، مع الحفاظ على التوافق العكسي الكامل مع C — أي كود C صحيح في Objective-C.

استحوذت Apple على NeXT (جنبًا إلى جنب مع Objective-C) في عام 1997. أصبحت اللغة أساس Cocoa وCocoa Touch — أطر العمل لنظامي macOS وiOS. منذ عام 2014، تروج Apple لـ Swift كبديل، لكن Objective-C لا تزال مهمة بشكل حاسم للمشاريع القديمة وبعض أطر العمل النظامية. وفقًا لـ Apple (WWDC 2024)، حوالي 35% من التطبيقات في App Store لا تزال تحتوي على كود Objective-C.

الميزة الرئيسية هي بيئة التشغيل الديناميكية. على عكس Swift، حيث يتم حل استدعاءات الدوال في وقت الترجمة، ترسل Objective-C الرسائل في وقت التشغيل عبر دالة objc_msgSend. يتيح ذلك تجاوز الدوال أثناء التنفيذ (method swizzling)، وإضافة الفئات ديناميكيًا، واستخدام forward invocation للمحددات غير الموجودة.

الصيغة: C + الإضافة كائنية التوجه

أي كود C صحيح في Objective-C. الإضافة كائنية التوجه تضيف الفئات (@interface/@implementation)، والتصنيفات، والبروتوكولات (@protocol)، والكتابة الديناميكية (id). الملفات لها امتدادات .m (تنفيذ) و.h (رؤوس).

صيغة الرسائل والإرسال الديناميكي

صيغة الرسائل هي الفرق الرئيسي بين Objective-C واللغات المشابهة لـ C. بدلاً من object.method(argument)، يُستخدم [object method:argument]. تمر كل رسالة عبر objc_msgSend، الذي يبحث ديناميكيًا عن تنفيذ الدالة في بيئة التشغيل.

objective-c
// صيغة الرسائل مع معاملات مسماة
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];
}

الإرسال الديناميكي يسمح بتجاوز الدوال في وقت التشغيل (method swizzling) — تقنية قوية ولكنها خطيرة. على سبيل المثال، أطر العمل مثل AFNetworking وAspects تستخدم swizzling لاعتراض استدعاءات URLSession. تحذر Apple: swizzling قد يعطل أطر العمل النظامية إذا استخدم بشكل غير صحيح.

التصنيفات وامتدادات الفئات

التصنيفات (Categories) هي ميزة فريدة في Objective-C تسمح بإضافة دوال إلى الفئات الموجودة (بما في ذلك فئات النظام مثل NSString وUIView) دون وراثة ودون الوصول إلى الكود المصدري. تُعلن التصنيفات عبر @interface ClassName (CategoryName).

objective-c
// ملف 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];
}
@end

الامتدادات (Extensions) هي نوع خاص من التصنيفات يُعلن في ملف .m بدون اسم: @interface ClassName (). على عكس التصنيفات، يمكن للامتدادات إضافة ليس فقط الدوال ولكن أيضًا ivar (متغيرات المثيل) والخصائص. تُستخدم الامتدادات لإخفاء API الداخلي عن الوحدات الخارجية.

الكتل (Blocks) — دوال مجهولة مع إغلاقات

الكتل (Blocks) هي دوال مجهولة في Objective-C تلتقط المتغيرات من النطاق الخارجي. صيغة الكتل: ^(int x) { return x * 2; }. تُستخدم الكتل في UIKit لمعالجات الاستدعاء، وفي Grand Central Dispatch للمهام غير المتزامنة، وفي مجموعات NSArray/NSDictionary للعمليات الوظيفية.

objective-c
// إعلان نوع الكتلة
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 lists [weak self].

ARC وMRC: إدارة الذاكرة

تطورت Objective-C من MRC (Manual Reference Counting) إلى ARC (Automatic Reference Counting). في MRC، كان المطور يستدعي يدويًا retain (زيادة العداد) وrelease (تقليله) وautorelease (التحرير المؤجل). الأخطاء في هذه الاستدعاءات تؤدي إلى تسرب الذاكرة أو تعطل التطبيق بسبب المؤشرات المعلقة.

العمليةMRCARC
إنشاء كائن[[Object alloc] init][[Object alloc] init]
الاحتفاظ بالمرجع[object retain]تلقائيًا
التحرير[object release]تلقائيًا
التحرير المؤجل[object autorelease]تلقائيًا (غير مطلوب)
المرجع الضعيف__weak لم يكن موجودًا__weak (nil تلقائي)

تم تقديم ARC في Xcode 4.2 وLLVM 3.0 (2011). يقوم المترجم تلقائيًا بإدراج retain/release في وقت الترجمة من خلال تحليل عمر الكائنات. ARC ليس جمعًا للقمامة — إنه تحليل ثابت مع إدراجات تلقائية. ARC في Objective-C متوافق مع ARC في Swift: كلاهما يستخدم نفس نظام عد المراجع على مستوى بيئة التشغيل.

التفاعل مع Swift عبر Bridging Header

الاستخدام المشترك لـ Objective-C وSwift في مشروع واحد هو ممارسة شائعة للمشاريع القديمة. توفر Apple Bridging Header — ملف يتم إنشاؤه تلقائيًا ترى من خلاله Swift فئات Objective-C، ويرى Objective-C فئات Swift التي ترث من NSObject.

objective-c
// 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 ملف <ProjectName>-Swift.h يحتوي على تعريفات @interface لفئات Swift المميزة بـ @objc.

swift
// فئة Swift مرئية من Objective-C
@objc class SwiftRouter: NSObject {
    @objc func navigateToProfile(userId: Int) {
        // تنفيذ
    }
}

القيود: أنواع القيم في Swift (struct, enum) غير مرئية مباشرة من Objective-C — يجب تغليفها في فئة مع @objc. الأدوية العامة (generics) في Swift ذات وصول محدود من Objective-C. النهج الموصى به هو كتابة كود جديد بلغة Swift وإعادة هيكلة كود Objective-C الموجود فقط عند تغيير الوظيفة المقابلة.

بيئة التشغيل وMethod Swizzling في Objective-C

الميزة الرئيسية لـ Objective-C على Swift هي الوصول الكامل إلى بيئة التشغيل. Method swizzling، استبدال تنفيذ الدوال في وقت التشغيل، يسمح بتجاوز دوال النظام دون وراثة. تستخدم المكتبات مثل Aspects وJRSwizzle هذه الإمكانية لـ AOP (البرمجة الموجهة بالجوانب) — المراقبة والتحليل والتسجيل.

Forward invocation هي ميزة أخرى لبيئة التشغيل: إذا لم يستجب كائن لمحدد، يستدعي النظام forwardInvocation:، مما يسمح بإعادة توجيه الرسالة إلى كائن آخر. هذا هو أساس نمط Proxy في Objective-C (NSProxy)، المستخدم للتهيئة البطيئة والكائنات الموزعة.

توصي Apple بتقليل استخدام حيل بيئة التشغيل في الكود الجديد، مفضلة الكتابة الثابتة لـ Swift. ومع ذلك، في المشاريع القديمة، معرفة objc_msgSend وmethod_exchangeImplementations وobjc_getAssociatedObject ضرورية لصيانة قاعدة الكود الموجودة.

الخصائص وKey-Value Observing

تدعم Objective-C الخصائص كسكر تركيب فوق ivar مع getters/setters. تحدد معدّلات atomic/nonatomic وstrong/weak/copy وreadonly/readwrite وassign/retain سلوك الذاكرة وأمان الخيوط. Key-Value Observing (KVO) هي آلية لمراقبة تغييرات الخصائص، مدمجة في بيئة التشغيل: يمكن لأي كائن الاشتراك في تغييرات خصائص كائن آخر عبر addObserver.

الأسئلة الشائعة

ما هي صيغة الرسائل في Objective-C؟

استدعاء الدالة يبدو كـ [object selector:argument]. تمر الرسالة عبر objc_msgSend، الذي يجد ديناميكيًا التنفيذ في بيئة التشغيل. المحدد (selector) هو اسم الدالة (@selector(methodName))، وليس مؤشرًا لدالة. يتيح ذلك swizzling وforward invocation.

كيف تختلف التصنيفات (Categories) عن الامتدادات (Extensions)؟

التصنيف (@interface ClassName (Name)) يضيف دوال إلى أي فئة (بما في ذلك فئات النظام) دون وراثة. الامتداد (@interface ClassName ()) يُعلن في ملف .m ويمكنه إضافة خصائص وivars. التصنيف لا يمكنه إضافة ivars، لكن الامتداد يمكنه.

ما هي الكتل (Blocks) في Objective-C؟

الكتل هي دوال مجهولة بصيغة ^(معاملات) { جسم }، تلتقط المتغيرات من السياق. تماثل lambdas في C++ وclosures في Swift. تتطلب __weak لمنع retain cycles عند التقاط self. تُستخدم في UIKit وGCD وFoundation.

ما الفرق بين ARC وMRC؟

MRC هو عد يدوي للمراجع: المبرمج يستدعي retain وrelease وautorelease. ARC تلقائي: المترجم يدرج retain/release بناءً على تحليل ثابت. ARC ليس GC — يتم تحرير الكائنات فورًا عند وصول العداد إلى الصفر. ARC يدعم معدّلات __weak و__strong.

هل يمكن استخدام Objective-C وSwift في نفس المشروع؟

نعم، عبر Bridging Header. ترى Swift Objective-C من خلال هذا الرأس، ويرى Objective-C Swift عبر <ProjectName>-Swift.h. يجب أن ترث فئات Swift من NSObject وتكون مميزة بـ @objc. Struct وenum في Swift غير مرئية مباشرة لـ Objective-C.

الخلاصة

  • Objective-C — مجموعة شاملة صارمة من C مع بيئة تشغيل ديناميكية وصيغة رسائل لـ Cocoa/Cocoa Touch
  • Message passing — استدعاءات عبر [object method] مع إرسال ديناميكي عبر objc_msgSend وقدرة swizzling
  • التصنيفات — إضافة دوال إلى الفئات الموجودة دون وراثة، بما في ذلك فئات النظام من Apple
  • الكتل — دوال مجهولة مع إغلاقات، تتطلب __weak لمنع retain cycles
  • ARC vs MRC — تطور من retain/release اليدوي إلى العد التلقائي للمراجع عبر المترجم
  • Bridging Header — آلية لعمل Swift وObjective-C معًا في مشروع واحد للترحيل التدريجي
  • الأهمية القديمة — حوالي 35% من تطبيقات App Store تحتوي على كود Objective-C يتطلب الصيانة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا