@Binding — ما هو، كيف يعمل وأمثلة في SwiftUI

المؤلف: IT Sectr نُشر: 2026-06-19 وقت القراءة: 7 دق

@Binding هو Property Wrapper في SwiftUI ينشئ مرجعاً للبيانات التي يملكها مكون آخر. Binding لا يخزن القيمة بنفسه — بل يوفر فقط الوصول إلى مصدر الحقيقة الموجود من خلال الإسقاط $. وفقاً لوثائق مطوري Apple (2025)، يوفر Binding اتصالاً تفاعلياً ثنائي الاتجاه بين العرض الأب والتابع دون ملكية مباشرة للبيانات. @Binding هو الآلية الرئيسية لتمرير الحالة القابلة للتغيير إلى أسفل التسلسل الهرمي.

النقاط الرئيسية

  • @Binding — Property Wrapper لإنشاء مرجع لحالة العرض الأب
  • بدون ملكية — Binding لا يخزن البيانات، بل يوفر فقط الوصول إلى مصدر الحقيقة
  • الإسقاط $ — $stateValue ينشئ Binding من @State أو @StateObject
  • ربط ثنائي الاتجاه — التغييرات في العرض التابع تنعكس فوراً في الأب
  • Binding.constant — قيمة ثابتة للنمذجة الأولية بدون تغذية راجعة

ما هو @Binding في SwiftUI؟

@Binding هو Property Wrapper ينشئ اتصالاً ثنائي الاتجاه بين خاصية مخزنة في العرض الأب ومكون تابع. الفرق الرئيسي بين Binding و@State: Binding لا يملك البيانات. هو يقرأ ويكتب القيم فقط من خلال المصدر الحقيقي — @State أو @StateObject أو Binding آخر في الأب. بدون Binding، لا يمكن للعروض التابعة تعديل حالة السلف بدون استدعاءات أو مفوضين.

يتم تنفيذ Binding كهيكل بخاصيتين: wrappedValue (القيمة الحالية) و projectedValue (Binding نفسه، يمكن الوصول إليه عبر $). عندما يغير العرض التابع wrappedValue من خلال Binding، ينقل SwiftUI التغيير إلى مصدر البيانات ويعيد رسم جميع العروض المعتمدة. يحدث هذا بشكل متزامن ضمن دورة التحديث الحالية.

ميزة مهمة: @Binding لا يقتصر على النقل أحادي المستوى. يمكن تمرير Binding عبر عدة مستويات من التسلسل الهرمي — يتلقى كل مكون تابع مرجعاً لنفس مصدر البيانات. أي تغيير في أي مستوى يؤدي إلى تحديث واحد لجميع العروض المرتبطة.

كيف يعمل الربط ثنائي الاتجاه لـ Binding

آلية الربط ثنائي الاتجاه من خلال @Binding تُبنى على إسقاطات Property Wrappers. عندما يعلن الأب @State var value: T، يولد SwiftUI تلقائياً الإسقاط $value من النوع Binding<T>. بتمرير $value إلى مكون تابع بـ @Binding var value: T، تقوم بربط كلا العرضين بنفس خلية الذاكرة. أي كتابة من خلال Binding في العرض التابع تؤدي إلى إعادة رسم كلا المكونين.

swift
struct SliderContainer: View {
    @State private var value: Double = 0.5

    var body: some View {
        VStack {
            Text("Value: \(value)")
            SliderView(value: $value)
        }
    }
}

struct SliderView: View {
    @Binding var value: Double

    var body: some View {
        Slider(value: $value, in: 0...1)
    }
}

في المثال، SliderContainer يملك @State value، و SliderView يتلقى Binding من خلال $value. الـ Slider داخل SliderView مرتبط بهذا Binding. عند سحب شريط التمرير، يغير Slider القيمة من خلال Binding، مما يحدث @State تلقائياً في SliderContainer، ويعرض كلا العرضين الرقم الحالي. السلسلة بأكملها تعمل بدون استدعاء أو إشعار واحد.

لإنشاء Binding من @StateObject أو @ObservedObject، يُستخدم نفس الإسقاط: $object.property يعطي Binding<PropertyType>. هذا يسمح بتمرير خصائص فردية لـ ObservableObject إلى العروض التابعة دون تمرير الكائن بأكمله. هذا النهج يوفر ارتباطاً أكثر دقة ويمنع إعادة الرسم غير الضرورية.

@Binding مقابل الاستدعاءات: ماذا تختار

قبل SwiftUI، كانت الطريقة القياسية لتمرير التغييرات لأعلى التسلسل الهرمي هي من خلال الاستدعاءات والمفوضين: يمرر الأب إغلاقاً، ويستدعيه المكون التابع عند التغيير. يقدم @Binding بديلاً بكود أقل وبناء جملة تصريحي أكثر. بدلاً من تمرير إغلاق إكمال، تمرر $stateValue ببساطة.

المعيار@Bindingالاستدعاءات
الكودتعليق توضيحي واحد + $إغلاق + استدعاء
متعدد المستوياتتلقائيسلسلة إغلاقات
الاختبارBinding(value:constant)إغلاقات وهمية
قابلية القراءةعاليةمتوسطة
المرونةبيانات فقطأي منطق

استخدم @Binding عندما يحتاج العرض التابع فقط لقراءة وتعديل قيمة. إذا كانت الآثار الجانبية مطلوبة عند التغيير (التحقق، التسجيل، طلب شبكة)، ادمج Binding مع استدعاء: مرر Binding للبيانات وإغلاقاً للأحداث. على سبيل المثال، يمكن لـ TextField الارتباط بـ Binding، بينما يقوم onChange بتشغيل التحقق.

أنماط استخدام @Binding في المشاريع

@Binding يُستخدم في عدة سيناريوهات نموذجية. الأول — عناصر تحكم مخصصة: مفاتيح، أشرطة تمرير، منتقي الألوان وعناصر تفاعلية أخرى تقبل Binding للمزامنة ثنائية الاتجاه. الثاني — النوافذ المشروطة: علم عرض الـ sheet يُمرر كـ Binding، مما يسمح للعرض التابع بإغلاق نفسه من خلال presentationMode أو تعيين مباشر.

النمط الثالث — نماذج مع فصل. إذا كان النموذج يتكون من حقول متعددة، يمكن استخراج كل حقل في مكون منفصل يقبل Binding لقيمته. هذا يبسط الاختبار وإعادة استخدام الحقول عبر نماذج مختلفة. يبقى المكون الأب المالك الوحيد لنموذج النموذج بأكمله.

swift
struct FormField: View {
    let title: String
    @Binding var text: String

    var body: some View {
        VStack(alignment: .leading) {
            Text(title).font(.caption)
            TextField("Enter \(title.lowercased())", text: $text)
                .textFieldStyle(.roundedBorder)
        }
    }
}

المكون FormField يقبل عنواناً و Binding لسلسلة نصية. يعرض تسمية و TextField مرتبطاً بـ Binding الممرر. يمكن لأي نموذج استخدام FormField عدة مرات بتمرير $property لكل حقل. هذا يقلل من تكرار الترميز ويوحد تصميم حقول النص.

إنشاء Bindings مخصصة

يسمح SwiftUI بإنشاء Binding يدوياً من خلال المُهيئ Binding(get:set:). هذا مفيد عندما تحتاج إضافة منطق عند قراءة أو كتابة قيمة. على سبيل المثال، يمكن إنشاء Binding يقوم بتنسيق رقم قبل الحفظ، أو Binding يقوم بمزامنة القيمة مع خادم بعيد عند كل تغيير.

swift
struct ValidatedField: View {
    @State private var email: String = ""

    var emailBinding: Binding<String> {
        .init(
            get: { email },
            set: { email = $0.lowercased().trimmingCharacters(in: .whitespaces) }
        )
    }

    var body: some View {
        TextField("Email", text: emailBinding)
    }
}

في القائمة، emailBinding المخصص يحول النص تلقائياً إلى أحرف صغيرة ويزيل المسافات عند كل تغيير. يستخدم TextField هذا Binding بدلاً من الارتباط مباشرة بـ $email. هذا النهج يركز التحقق من الصحة وتحويل البيانات داخل Binding دون إرباك الكود بمعالجات onChange.

أخطاء وأنماط مضادة مع @Binding

الخطأ الأول والأكثر شيوعاً هو تمرير قيمة بدلاً من Binding. إذا أعلن مكون تابع @Binding var text: String، ومرر الأب text (بدون $)، سيعطي المترجم خطأ: Cannot convert value of type 'String' to expected argument type 'Binding<String>'. الحل — استخدم دائماً البادئة $ عند التمرير: $text.

الخطأ الثاني — Binding على بيانات للقراءة فقط. إذا كان العرض التابع يحتاج فقط لقراءة قيمة، لا تستخدم @Binding — يكفي let بسيط أو @State من الأب. Binding implies القدرة على الكتابة، وأذونات التعديل الزائدة تعقد التصحيح وتنتهك مبدأ الامتياز الأقل.

المشكلة الثالثة — Binding.constant في الإنتاج. Binding.constant(value) ينشئ ربطاً وهمياً بدون تغذية راجعة — يتم تجاهل التغييرات. استخدم constant فقط للنمذجة الأولية والمعاينات (Xcode Previews)، ولكن أبداً في الكود الحقيقي. للاختبارات، استخدم Binding(get:set:) بسلوك متحكم به.

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

ما الفرق بين @Binding و @State؟

@State يملك البيانات ويدير تخزينها في الكومة. @Binding فقط يشير إلى الحالة الموجودة بدون ملكية. @State دائماً خاص، @Binding هو معلمة إدخال للعرض التابع.

هل يمكن إنشاء Binding بدون @State؟

نعم، من خلال المُهيئ Binding(get:set:) أو Binding.constant(value). يمكن أيضاً الحصول على Binding من @StateObject عبر الإسقاط $object.$property ومن Publisher عبر Binding(get:set:) داخل Subscribe.

كيفية تمرير Binding عبر عدة مستويات من التداخل؟

@Binding يُمرر عبر سلسلة: كل مكون وسيط يعلن @Binding ويمرره للأمام عبر $. جميع المستويات تشير إلى نفس مصدر البيانات في العرض الجذر.

لماذا لا يقوم Binding.constant بتحديث الواجهة؟

Binding.constant ينشئ غلافاً صامتاً — setter يتجاهل القيم الجديدة. هو مخصص فقط للنمذجة الأولية ومعاينات SwiftUI حيث لا تكون التغذية الراجعة من المكون التابع مطلوبة.

هل يمكن أن يكون @Binding اختيارياً؟

نعم، Binding<T?> مدعوم. إذا مررت Binding<String?>، سيتمكن العرض التابع من تعيين nil. هذا مناسب لحقول النماذج الاختيارية أو الحالات مع إمكانية إعادة التعيين.

الخلاصة

  • @Binding — Property Wrapper للربط ثنائي الاتجاه مع بيانات العرض الأب
  • لا يملك البيانات — فقط يوفر الوصول إلى مصدر الحقيقة
  • الإسقاط $ يحول @State، @StateObject إلى Binding لتمريره للعروض التابعة
  • Binding مخصص يُنشأ عبر Binding(get:set:) مع منطق إضافي
  • Binding.constant — فقط للمعاينات والنماذج الأولية
  • نقل متعدد المستويات — Binding يمر عبر أي عمق تداخل
  • بديل للاستدعاءات — طريقة تصريحية لتعديل الحالة من المكونات التابعة

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

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

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

اقرأ أيضًا