UIKit هو إطار عمل لبناء واجهات رسومية في تطبيقات iOS وmacOS. تشمل المجموعة UIView وUIViewController وعناصر التحكم ونظام Auto Layout، مما يتيح إنشاء شاشات تفاعلية ومتكيفة. وفقًا لوثائق Apple Developer (2025)، يحتوي UIKit على أكثر من 200 فئة للعمل مع النوافذ والعروض والرسوم المتحركة والإيماءات والنصوص — وهو أساس جميع تطبيقات iPhone وiPad.
الوجبات الرئيسية
UIKit هو إطار عمل من Apple يوفر فئات لإنشاء وإدارة واجهات المستخدم على iOS وiPadOS وmacOS (عبر Mac Catalyst). يعمل فوق Core Animation وCore Graphics وQuartz Core، مما يُجرّد العرض منخفض المستوى إلى كائنات عالية المستوى — الأزرار والتسميات والصور والحاويات. ظهر UIKit مع iPhone OS 1 في عام 2007 ولا يزال الإطار الرئيسي لتطوير iOS إلى جانب SwiftUI.
يتبع الإطار نهجًا أمرّيًا: ينشئ المطور مثيلات لفئات UIButton وUILabel وUIImageView ويحدد خصائصها (اللون والخط والموضع) ويضيفها إلى التسلسل الهرمي للعروض عبر addSubview. كل تغيير في الواجهة يتم بشكل صريح — لا توجد تحديثات سحرية خلف الكواليس. هذا يميّز UIKit عن الأطر التصريحية مثل SwiftUI، حيث وصف الحالة يُعيد رسم الواجهة تلقائيًا.
يشمل الإطار عدة فئات من الفئات. UIView هو العنصر الأساسي الذي ترث منه جميع المكونات المرئية. UIWindow هو الحاوية عالية المستوى التي تُعرض من خلالها العروض على الشاشة. UIViewController يدير مجموعة من العروض ويستجيب لتدوير الشاشة وظهور لوحة المفاتيح وإشعارات النظام. UIApplication هو نقطة الدخول التي تعالج أحداث اللمس وضغطات الأزرار.
للنصوص، تُستخدم UILabel (نص ثابت) وUITextField (إدخال سطر واحد) وUITextView (إدخال متعدد الأسطر). للأزرار — UIButton، بما في ذلك أزرار النظام والمخصصة وأيقونات SF Symbols. للتنقل — UINavigationController وUITabBarController وUISplitViewController. إجمالاً، يحتوي UIKit على أكثر من 200 فئة عامة.
هندسة UIKit مبنية على طبقات: كل طبقة مسؤولة عن جانبها الخاص من العرض. في المستوى الأدنى يوجد Core Graphics — محرك عرض المسارات والنصوص والصور. فوقه Core Animation، الذي يدير تكوين الطبقات (CALayer) والرسوم المتحركة بين الحالات. يبني UIKit واجهة برمجة تطبيقات موجهة للكائنات فوقهما: UIView وUIViewController وUIResponder.
كل تطبيق له تسلسل هرمي للعروض — شجرة يكون جذرها UIWindow. تحته UIViewController الجذر وعرضه والعروض الفرعية المتداخلة داخله. تنتشر أحداث اللمس على طول سلسلة المستجيبين: من العرض الأكثر تداخلاً إلى والديه وحتى UIApplication. إذا لم يعالج أي كائن اللمس، يتم تجاهله.
كل UIView يحتوي على CALayer تتعامل مع عرض البكسلات على الشاشة. يدير العرض اللمس وإمكانية الوصول؛ وتتعامل الطبقة مع الرسومات — الظل وcornerRadius والحدود والتحويل. يتيح هذا الفصل إسناد الرسومات الثقيلة إلى سلسلة منفصلة (خادم العرض) دون حظر السلسلة الرئيسية. توصي Apple بالعمل مباشرة مع CALayer إذا كان هناك أكثر من 200 عرض على الشاشة — مما يقلل من حمل وحدة المعالجة المركزية.
تبدأ سلسلة المستجيبين بالكائن الذي يستقبل أولاً حدث لمس. إذا لم يعالج الحدث (طريقة touchesBegan غير معمول عليها)، ينتقل الحدث إلى المستجيب التالي في السلسلة: next وsuperview وnext responder وUIViewController وUIWindow وUIApplication وApp Delegate. يتيح هذا اعتراض الإيماءات العالمية وأحداث لوحة المفاتيح على مستوى المشهد دون إضافة معالج لكل عرض.
كل UIViewController يمر عبر تسلسل أحداث محدد بدقة. تشمل دورة الحياة المراحل: التهيئة وتحميل العرض والظهور على الشاشة وتحديث التخطيط عند التدوير والإخفاء والخروج من الشاشة وتحرير الذاكرة. يقوم المطور بتجاوز الطرق المقابلة لتنفيذ كود مخصص في كل مرحلة.
class ProfileViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadUserProfile()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
clearCache()
}
}
في viewDidLoad يتم تكوين الواجهة — إنشاء العروض الفرعية وتعيين القيود والاشتراك في المفوّضين. في viewWillAppear تُجرى العمليات قبل العرض: تحميل بيانات جديدة من الشبكة وتحديث القيم. viewDidDisappear هو مكان إلغاء الاشتراك من الإشعارات وتنظيف البيانات المؤقتة. استدعاء super إلزامي في جميع التجاوزات، وإلا تنكسر سلسلة الأحداث.
في إصدارات iOS القديمة، كانت توجد طريقة viewDidUnload تُستدعى عند نقص الذاكرة. منذ iOS 6 تمت إزالة الطريقة — الآن UIKit يُفرغ تلقائيًا عروض المتحكمات عندما لا تكون مرئية. يحتاج المطور فقط إلى تعريف جميع مراجع العروض كـ weak ليتمكن ARC من تحرير الذاكرة بشكل صحيح عند استلام تحذير من النظام.
يدعم UIKit نوعين من الانتقالات: segue (عبر Storyboard) والتنقل البرمجي عبر UINavigationController. يبدو الانتقال البرمجي هكذا: navigationController?.pushViewController(detailVC, animated: true). في هذه الحالة، تمر دورة حياة detailVC كالمعتاد — يُستدعى viewDidLoad مرة واحدة، ويُستدعى viewWillAppear في كل مرة يظهر فيها.
Auto Layout هو نظام تحديد المواقع القائم على العلاقات الرياضية (القيود). بدلاً من إحداثيات X وY الثابتة، يصف المطور قواعد: «الزر على يمين التسمية بهامش 16pt» أو «العرض يمتد عبر عرض الشاشة بهامش 20pt من اليسار واليمين». يحل النظام نظام المعادلات الناتج في وقت التشغيل، مُكيّفًا الواجهة مع أي حجم شاشة.
يمكن تعيين القيود في Interface Builder (عبر السحب والإفلات) أو برمجيًا في Swift. كل قيد هو مثيل لفئة NSLayoutConstraint مع معلمات: firstItem وfirstAttribute وrelation وsecondItem وsecondAttribute وmultiplier وconstant. تُفعّل القيود عبر isActive = true أو بشكل جماعي عبر NSLayoutConstraint.activate().
مع إطلاق iPhone X (2017)، قدمت Apple Safe Area — منطقة الشاشة الخالية من النتوء والزوايا المستديرة ومؤشر الشريط الرئيسي. يجب ربط القيود بـ view.safeAreaLayoutGuide وليس بـ view. Layout Margins يضيف حشوة داخلية للعرض، افتراضيًا 8pt أو 16pt حسب السياق. استخدام safeAreaLayoutGuide يضمن العرض الصحيح على جميع أجيال iPhone وiPad.
يدعم Auto Layout التحريك عبر تغيير ثوابت القيود. ببساطة قم بتحديث constant لقيد واستدع UIView.animate مع layoutIfNeeded داخل كتلة التحريك. يعيد النظام حساب موضع جميع العروض في التسلسل الهرمي بسلاسة. تُستخدم هذه التقنية للكتل القابلة للتوسيع ولوحات المفاتيح المتكيفة وتغييرات اتجاه الشاشة.
UITableView وUICollectionView هما أداتان قويتان في UIKit لعرض القوائم والشبكات. UITableView مناسبة للقوائم الرأسية أحادية العمود (الدردشة والإعدادات وتدفق الأخبار). UICollectionView للشبكات والقوائم الأفقية والعربات والتخطيطات المخصصة (المعرض والمنتجات والتقويم). تستخدم كلتا الفئتين نمط التفويض لفصل البيانات عن المظهر.
مصدر البيانات هو بروتوكول UITableViewDataSource بالطرق الإلزامية numberOfRowsInSection وcellForRowAt. UITableViewDelegate يعالج النقرات على الخلايا وارتفاعات الصفوف وأحداث التمرير. آلية reuse identifier تعيد استخدام الخلايا التي خرجت من الشاشة، وهو أمر بالغ الأهمية للأداء في القوائم الكبيرة.
class ContactsViewController: UITableViewController {
private let contacts = ["آنا", "بوريس", "فيكتور"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self,
forCellReuseIdentifier: "cell")
}
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath)
var content = cell.defaultContentConfiguration()
content.text = contacts[indexPath.row]
cell.contentConfiguration = content
return cell
}
}
يظهر المثال متحكمًا بسيطًا لعرض مصفوفة من السلاسل. يتم تكوين الخلية عبر UIListContentConfiguration — واجهة برمجة تطبيقات حديثة (iOS 14+) حلت محل textLabel وdetailTextLabel القديمين. تسجيل فئة الخلية في viewDidLoad إلزامي، وإلا سيتعطل التطبيق باستثناء وقت التشغيل.
بدءًا من iOS 13، توصي Apple بـ UICollectionViewCompositionalLayout لبناء تخطيطات معقدة. يصف المطور القسم والمجموعة والعنصر وأحجامها بشكل تصريحي — للحصول على شبكة بهندسة عشوائية: شريط أو شبكة 2x2 أو عربة أو زخرفة. حل Compositional Layout محل UICollectionViewFlowLayout القديم لجميع المشاريع الجديدة. مع DiffableDataSource، يتقلص تحديث المجموعة إلى استدعاء واحد apply(snapshot)، وتتم رسوم التغيير المتحركة تلقائيًا.
فيما يلي مثالان عمليان لاستخدام UIKit في مهام حقيقية: إنشاء عرض مخصص بظل وزوايا مستديرة، ومعالجة إيماءة السحب لحذف عنصر من قائمة.
extension UIView {
func applyCardStyle() {
layer.cornerRadius = 12
layer.shadowOpacity = 0.15
layer.shadowRadius = 8
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.masksToBounds = false
}
}
@objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
guard let swipedView = gesture.view else { return }
UIView.animate(withDuration: 0.3) {
swipedView.alpha = 0
swipedView.transform = CGAffineTransform(translationX: 300, y: 0)
} completion: { _ in
swipedView.removeFromSuperview()
}
}
إضافة applyCardStyle تضيف ظلًا وزوايا مستديرة لأي عرض — مفيد لبطاقات المنتجات والملفات الشخصية والإشعارات. طريقة handleSwipe مع التحريك تحذف عنصرًا عندما يسحب المستخدم لليمين عليه. يُضاف المعالج إلى العرض عبر addGestureRecognizer مع تهيئة UISwipeGestureRecognizer(direction: .right). تعيين masksToBounds = false مهم لمنع قص الظل بحدود العرض.
لواجهات أكثر تعقيدًا، استخدم UIStackView — حاوية توزع تلقائيًا العروض المتداخلة أفقيًا أو عموديًا. UIStackView يُبسّط التخطيط: لا حاجة لتعيين قيود لكل عنصر، يكفي قيد واحد للـ stack نفسه.
الأسئلة الشائعة
Frame هو مستطيل بإحداثيات superview (الموضع + الحجم). Bounds هو مستطيل بإحداثيات العرض الخاصة (يبدأ دائمًا من 0,0). Frame يتغير عند التدوير والتحجيم؛ bounds لا يتغير.
UIKit يُفرغ تلقائيًا عروض المتحكمات المخفية. يحتاج المطور فقط إلى تعريف خصائص العروض كـ weak var ليتمكن ARC من تحرير الذاكرة عند استلام تحذير النظام.
للمشاريع الجديدة، توصي Apple بـ SwiftUI. إذا كان المشروع يستخدم UIKit — استخدم XIB للشاشات الفردية أو التخطيط البرمجي عبر SnapKit. Storyboard يُنشئ تعارضات دمج ويبطئ البناء.
استخدم UIColor مع دعم traitCollection: UIColor { $0.userInterfaceStyle == .dark ? ... : ... }. فعّل الوضع الداكن في Info.plist بمفتاح UIUserInterfaceStyle.
UIStackView يحسب تلقائيًا مواضع وأحجام العروض المتداخلة بناءً على alignment وdistribution وspacing. يقلل كود القيود بنسبة 60–80% ويُبسّط التكيف مع الشاشات المختلفة.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.