لدعم إصدارات macOS الأقدم، أنشئ التطبيق باستخدام SDK يتضمن تعريفات واجهات API الأحدث، وحدد هدف نشر أدنى مدعومًا، وأحط الاستدعاءات الأحدث بفحوصات التوافر وبدائل عملية. يوضح هذا الدليل كيفية إبقاء نافذة ملاحظات أصلية صغيرة قابلة للاستخدام على macOS 12 مع اعتماد عرض من macOS 14.

ما إعدادات التوافق التي يجب أن تتوافق؟

بالنسبة إلى مطوّر تطبيقات Mac، تتمثل المهمة العملية في إنشاء تطبيق واحد يعمل على أقدم إصدار مدعوم ويستخدم الميزات الأحدث عند توفرها. ابدأ بالفصل بين ثلاثة مدخلات: يفهم المترجم لغة المصدر، ويوفر SDK تعريفات واجهات API، ويحدد هدف النشر أقدم بيئة تشغيل مستهدفة. يعرّف مرجع إعدادات البناء من Apple المتغير SDKROOT بأنه SDK الذي تشارك ترويساته ومكتبته في عملية البناء. مرجع إعدادات البناء

يمكن استخدام SDK أحدث مع هدف نشر أقدم. توثّق Clang صراحةً إمكانية البناء باستخدام أحدث SDK مع اختيار حد أدنى أقدم لـ macOS عبر -mmacos-version-min=. ويتطلب هذا الجمع مع ذلك إجراء فحوصات التوافر حول واجهات API التي طُرحت بعد الحد الأدنى. امتدادات لغة Clang

اختر حدًا أدنى يدعمه إصدار Xcode الذي حددته فعليًا. يميّز جدول التوافق من Apple بين إصدار macOS اللازم لتشغيل Xcode وأهداف النشر التي يمكنه البناء لها. إذا كان الحد الأدنى الذي تريده خارج النطاق المدعوم لسلسلة الأدوات هذه، فاختر سلسلة أدوات مدعومة مناسبة أو عدّل الحد الأدنى للتطبيق قبل تنفيذ البدائل. حِزم SDK ومتطلبات النظام

في هذا المثال الافتراضي، المتطلبات هي macOS 12 أو أحدث، وSDK يتضمن واجهات API الخاصة بـ macOS 14، ونافذة ملاحظات بحالتين: مجموعة فارغة وملاحظة نموذجية واحدة. عرض الحالة الفارغة الأحدث اختياري؛ أما عرض الملاحظة فيظل متاحًا على النظام الأساسي.

حدّد الحد الأدنى في تكويني البناء

في Build Settings لهدف التطبيق، عيّن MACOSX_DEPLOYMENT_TARGET إلى 12.0 لكل من Debug وRelease. إذا كنت تدير الإعدادات في ملفات تهيئة، فهذا مقطع تهيئة كامل، وليس برنامجًا:

MACOSX_DEPLOYMENT_TARGET = 12.0

عيّن ملف التهيئة إلى التكوينات المطلوبة في علامة التبويب Info للمشروع. ثم تحقق من القيمة النهائية للهدف: توثّق Apple أن إعدادات الهدف قد تتجاوز القيم المقدمة في ملف تهيئة معيّن. مجرد إضافة الملف إلى المشروع لا يجعل إعداداته نافذة. إضافة ملف تهيئة بناء إلى مشروعك

كيف تضيف واجهة API أحدث من دون رفع الحد الأدنى للتطبيق؟

تفحص عبارة Swift if #available التوافر وقت التشغيل، وتُعلم المترجم بواجهات API المسموح بها داخل ذلك الفرع. أبقِ البديل ضمن القرار نفسه كي يحصل النظام الأقدم على تنفيذ مكتمل. يغطي الرمز * المطلوب المنصات غير المذكورة صراحةً؛ لكنه لا يجعل واجهة macOS API المذكورة متاحة في الإصدارات الأقدم. تدفق التحكم — التحقق من توافر واجهات API

تتوفر ContentUnavailableView من Apple بدءًا من macOS 14، وتدعم عرض المحتوى الفارغ. هنا، توفر VStack صغيرة العرض المقابل على macOS 12 و13. ينقل الفرعان الإجراء التالي نفسه. ContentUnavailableView

تطبيق SwiftUI افتراضي كامل

أنشئ مشروع تطبيق macOS باسم CompatibilityNotes، واختر Swift وSwiftUI، واضبط هدف النشر على 12.0. استخدم SDK يتضمن واجهات API الخاصة بـ macOS 14. استبدل تعريفات التطبيق وعرض المحتوى التي أنشأها المشروع بالملف الواحد التالي، وتأكد من أن الهدف يحتوي على تعريف واحد فقط لـ @main. لا حاجة إلى أصول أو حزم أو ملفات إدخال.

import SwiftUI

@main
struct CompatibilityNotesApp: App {
    var body: some Scene {
        WindowGroup {
            NotesView()
        }
    }
}

struct NotesView: View {
    @State private var notes: [String] = []

    var body: some View {
        VStack(spacing: 16) {
            if notes.isEmpty {
                emptyState
            } else {
                List(notes, id: \.self) { note in
                    Text(note)
                }
            }

            Button(notes.isEmpty ? "Add sample note" : "Reset sample") {
                if notes.isEmpty {
                    notes = ["Sample note: arrange the blue shapes."]
                } else {
                    notes = []
                }
            }
        }
        .padding()
        .frame(minWidth: 360, minHeight: 240)
    }

    @ViewBuilder
    private var emptyState: some View {
        if #available(macOS 14.0, *) {
            ModernEmptyState()
        } else {
            VStack(spacing: 8) {
                Text("No notes")
                    .font(.headline)
                Text("Add a sample note to begin.")
            }
        }
    }
}

@available(macOS 14.0, *)
private struct ModernEmptyState: View {
    var body: some View {
        ContentUnavailableView {
            Label("No notes", systemImage: "note.text")
        } description: {
            Text("Add a sample note to begin.")
        }
    }
}

السلوك المقصود مباشر: يعرض macOS 12 و13 النص البديل؛ ويعرض macOS 14 والإصدارات الأحدث ContentUnavailableView. يؤدي اختيار Add sample note إلى عرض الملاحظة الافتراضية. ويؤدي اختيار Reset sample إلى استعادة الحالة الفارغة. يحتفظ هذا العرض التوضيحي بالبيانات في الذاكرة ولا يحفظ الملاحظات بين مرات التشغيل.

يقيّد التعليق التوضيحي @available استخدام الدالة المساعدة بنظام macOS 14 والإصدارات الأحدث. ويستوفي فرع #available لدى المستدعي هذا القيد. يصف التعليق التوضيحي مدى توافر تعريف؛ لكنه لا يوفر تنفيذًا للإصدارات الأقدم. السمات — available

تمت مراجعة هذا المثال بالاستناد إلى الوثائق المسترجعة، لكنه لم يُبنَ أو يُشغّل: كانت بيئة التنفيذ المتاحة Linux، ولم يكن Swift أو Clang مثبتًا فيها. ولا تزال الحاجة قائمة إلى التحقق من البناء والتشغيل على macOS.

ما الذي تحله فحوصات التوافر عند الربط؟

لا يفيد فرع وقت التشغيل إلا إذا أمكن تحميل الملف التنفيذي. توثّق Clang أن التعريفات المشروحة بالتوافر والتي طُرحت بعد هدف النشر يمكن عادةً ربطها ربطًا ضعيفًا. يسمح المرجع الضعيف بغياب التعريف وقت التشغيل؛ لكن على التطبيق أن يتجنب استخدامه عند غيابه. لذلك يهم هدف النشر والتعريفات التي يراها المترجم، إلى جانب الفرع. السمات في Clang — التوافر

في المثال، أبقِ الربط مع SwiftUI عاديًا: فالإطار موجود أصلًا في الأساس الذي يمثله macOS 12. أَحِط العرض الأحدث بحد التوافق. إذا كان إطار جديد بالكامل غائبًا عن النظام الأساسي، فتحقق من تبعية الإطار نفسها؛ فإحاطة استدعاء واحد لا تحل كل متطلبات التحميل. يشرح دليل الربط الضعيف من Apple الفرق بين السماح بغياب رمز واستخدام ذلك الرمز فعليًا. الأطر والربط الضعيف

استخدم صياغة التوافر الخاصة بلغة المصدر:

لغة المصدر شرط التوافر وقت التشغيل
Swift if #available(macOS 14.0, *)
Objective-C أو Objective-C++ if (@available(macOS 14.0, *))
C أو C++ مع دعم Clang لمنصات Apple if (__builtin_available(macOS 14.0, *))

توثّق Clang صياغة Objective-C والميزة المضمنة في C/C++، إلى جانب -Wunguarded-availability. فعّل تشخيصات التوافر لشفرة عائلة C، وتحقق من التحذيرات قبل اعتبار هدف النشر الأقدم صالحًا للاستخدام. امتدادات لغة Clang

ماذا لو لم يتضمن SDK المستخدم في البناء واجهة API؟

لا يستطيع فحص وقت التشغيل توفير تعريف غير موجود في SDK. إذا لم يتمكن المترجم من التعرّف على ContentUnavailableView، فأنشئ التطبيق باستخدام SDK يتضمنها. وإذا كان على المشروع أيضًا أن يُبنى باستخدام حِزم SDK أقدم، فاحتفظ بترتيب مشروط مقصود للمصادر يستبعد المراجع غير المدعومة من تلك البِنى.

تختبر #if compiler(...) في Swift إصدار المترجم، بينما تختبر #if canImport(...) إمكانية استيراد وحدة. لا يثبت أي من الشرطين أن عضوًا بعينه في وحدة موجودة متاح على جهاز Mac قيد التشغيل. استخدم شروط الترجمة هذه للأغراض الموثقة لها، ثم استخدم فحوصات التوافر وقت التشغيل عند الحاجة. العبارات — كتلة الترجمة الشرطية

متى يغيّر استقرار ABI في Swift وحدود مكتبة C++ الإجابة؟

لا يجعل استقرار ABI في Swift كل ميزة أحدث في المكتبة القياسية أو وقت التشغيل متاحة على الأنظمة الأقدم. يميّز شرح Swift بين وضع لغة المصدر ودعم وقت التشغيل: فتغيير وضع اللغة اختيار وقت الترجمة، بينما قد تتطلب الميزات التي تحتاج إلى وظائف جديدة في وقت التشغيل إصدارًا معينًا من نظام التشغيل. اتبع متطلبات التوافر للميزة المحددة التي تعتمدها. تطوير Swift على منصات Apple بعد استقرار ABI

يوجد فصل مشابه في C++ بين دعم المترجم ودعم المكتبة. توفر Apple مترجم Apple Clang عبر Xcode ووقت تشغيل libc++ عبر حِزم SDK وأنظمة التشغيل. يحدد جدول الميزات المتطلبات التي قد تعتمد على المكتبة المشتركة التي يوفرها نظام التشغيل. إن اختيار -std=c++17 أو -std=c++20 لا يثبّت وظائف وقت التشغيل هذه على جهاز Mac الخاص بالمستخدم. دعم لغة C++

تحويل الأعداد مثال مفيد: تحدد Apple إصدار macOS 10.15 حدًا أدنى للدالتين std::to_chars وstd::from_chars مع الأنواع الصحيحة، وإصدار macOS 13.3 للدالتين مع أنواع الفاصلة العائمة. لذلك يحتاج تطبيق macOS 12 إلى تنفيذ تحويل متوافق إذا كان سيتطلب خلاف ذلك نسختي الدالتين الخاصتين بالفاصلة العائمة. تحقّق من النسخة المحددة، لا من الترويسة أو إصدار معيار C++ فحسب. دعم لغة C++

لا تفترض أن إحاطة كل استدعاء لمكتبة C++ بـ __builtin_available كافية. تتضمن سمات التوافر في Clang صيغة strict ترفض الاستخدام عند استهداف منصة أقدم، كما تستخدم libc++ علامات التوافر لتشخيص غياب دعم وقت التشغيل أثناء الترجمة. عندما ترفض الترويسات المحددة العملية، استخدم تنفيذًا متوافقًا مع النظام الأساسي أو ارفع الحد الأدنى. السمات في Clang — التوافر، توثيق المورّد — علامات التوافر

حافظ على إعدادات ABI الخاصة بالمكتبة عبر التبعيات. توثّق LLVM ضمانات ABI المحددة وحدودها، بما في ذلك احتمال عدم عمل الشفرة المترجمة باستخدام ترويسات libc++ أحدث مع مكتبة أقدم. إن أعلام إعدادات ABI التي تغيّرها هي ضوابط خاصة بالمورّد. وتغييرها في شفرة التطبيق ليس بديلًا عن وقت تشغيل متوافق. ضمانات ABI لمكتبة libc++

كيف تشخّص البناء المكتمل وتتحقق منه؟

استخدم مرحلة الإخفاق لاختيار التحقيق التالي. تتبع أداة المساعدة هذه حدود المترجم والتوافر ووقت التشغيل الموضحة أعلاه؛ وهي تسلسل تشخيصي، وليست ادعاءً بأن العينة اجتازت الاختبار.

العَرَض ابدأ بالتحقق من الخطوة العملية التالية
اسم واجهة API الجديدة غير معروف تعريفات SDK اختر SDK يتضمن واجهة API.
واجهة API أحدث من هدف النشر استخدام بلا حماية أضف حد توافر مدعومًا وبديلًا.
ما زالت عملية مكتبة C++ مرفوضة متطلبات النسخة المحددة والمكتبة استخدم تنفيذًا متوافقًا أو عدّل الحد الأدنى.
يفشل التطبيق قبل ظهور نافذته متطلبات التحميل والتبعيات افحص المكتبة أو الرمز المفقود الذي أُبلغ عنه.
تتعطل الميزة الأحدث وحدها العمل المنفّذ خارج الفرع المحمي افحص الإنشاء والتهيئة واستدعاءات الدوال المساعدة.
يعمل البناء على عائلة معالجات واحدة فقط معماريات الملف التنفيذي والتبعيات ابنِ واختبر شرائح المعماريات المطلوبة.

دعم المعماريات متطلب إضافي. تغطي إرشادات Apple للملفات الثنائية الشاملة arm64 وx86_64، بما يشمل المكتبات والأطر المترجمة. تحقّق من التبعيات إلى جانب الملف التنفيذي للتطبيق؛ فنجاح البناء على جهاز Mac المخصص للتطوير لا يثبت إلا توافق ذلك البناء. بناء ملف macOS ثنائي شامل

في هذه العينة، أنشئ إصدار Release واختبر التطبيق الناتج على macOS 12 وmacOS 13 وmacOS 14 أو أحدث، باستخدام أجهزة مدعومة. على كل نظام، شغّل التطبيق مع المجموعة الفارغة، وأضف الملاحظة النموذجية، ثم أعد ضبطها. ينبغي للإصدارات الأقدم أن تحافظ على التفاعل الكامل عبر البديل. اختبر كل معمارية تنوي توزيع التطبيق عليها.

أبقِ حدود الدعم واضحة مع نمو التطبيق: هدف نشر مدعوم، وتعريفات من SDK مناسب، ووظائف أحدث محمية، وتنفيذ أساسي مفيد. ينبغي أن تتوافق كل واجهة API أو تبعية إضافية مع المتطلبات نفسها قبل إدراجها في البناء.

المصادر