.modifier(): ما هو، طريقة تطبيق المعدّلات في SwiftUI

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

.modifier() هو method من بروتوكول View في SwiftUI يطبّق نسخة مخصصة من ViewModifier على أي نوع View. وفقًا لـ Apple Developer Documentation, 2024، يستقبل method ViewModifier ويعيد ModifiedContent، ليغلف View الأصلية في نسخة معدّلة. على عكس المعدّلات المدمجة، وهي methods امتداد بمعاملات ثابتة، يسمح .modifier() باستخدام أي منطق مخصص مغلف في نوع يطبّق بروتوكول ViewModifier.

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

  • .modifier() — method لتطبيق ViewModifier مخصص على View
  • ModifiedContent — نوع الإرجاع الذي يخزن View الأصلية والمعدّل
  • المعدّلات المخصصة تُنشأ عبر بروتوكول ViewModifier
  • سلسلة استدعاءات .modifier() تنشئ تسلسلاً هرميًا من أغلفة ModifiedContent
  • التطبيق الشرطي يُطبّق عبر if/else أو معاملات المعدّل

ما هو .modifier() في SwiftUI؟

.modifier() هو method مُعلَن في بروتوكول View: func modifier<M: ViewModifier>(_ modifier: M) -> ModifiedContent<Self, M>. يستقبل نسخة من نوع يطبّق ViewModifier ويعيد View معدّلة مغلفة في نوع ModifiedContent.

ظهر method في iOS 13 وهو الطريقة الرئيسية لتطبيق المعدّلات المخصصة في SwiftUI. على عكس المعدّلات المدمجة (font, foregroundColor, frame) التي تُستدعى مباشرة على View، يتطلب .modifier() إنشاء نوع المعدّل مسبقًا. هذا يضيف مستوى من التجريد لكنه يفتح إمكانيات لإعادة الاستخدام والوسم (parameterization).

وفقًا لـ Hacking with Swift (2024)، يُستخدم .modifier() في كل مشروع SwiftUI حيث نحتاج نمطًا موحدًا لعناصر واجهة مستخدم متكررة. لا يضيف method overhead مقارنة بتسلسل المعدّلات المدمجة — المحسّن (compiler) يضبط الاستدعاء.

التوقيع والأنواع

يقبل method modifier معاملًا عامًا M مقيدًا ببروتوكول ViewModifier. بفضل العموميات (generics)، يعرف المحسّن (compiler) النوع الملموس للمعدّل ويمكنه تحسين نوع View الناتج دون محو النوع (type erasure).

كيف يعمل method modifier(_:)؟

method modifier(_:) ينشئ نسخة ModifiedContent تربط View الأصلية (Self) بالمعدّل المُمرَر (M). أثناء التقديم (rendering)، يستدعي SwiftUI M.body(content: self)، مُمرِرًا View الأصلية كمعامل content.

swift
struct RoundedBorder: ViewModifier {
    let color: Color
    let width: CGFloat

    func body(content: Content) -> some View {
        content
            .padding(8)
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(color, lineWidth: width)
            )
    }
}

// التطبيق عبر .modifier():
Text("مرحبًا")
    .modifier(RoundedBorder(color: .blue, width: 2))

// السلسلة المباشرة المكافئة:
Text("مرحبًا")
    .padding(8)
    .overlay(
        RoundedRectangle(cornerRadius: 8)
            .stroke(Color.blue, lineWidth: 2)
    )

ترتيب التطبيق: تُطبّق المعدّلات من الخارج إلى الداخل. أول استدعاء .modifier() يغلف View من الخارج، والثاني — فوق الأول، وهكذا. هذا مهم عند التكوين — الترتيب يؤثر على النتيجة البصرية.

وفقًا لـ Apple WWDC 2022، يستخدم SwiftUI diffing قائم على الهوية (Identity-based) لاكتشاف التغييرات في تسلسل ModifiedContent. نوع المعدّل (M) يشارك في تشكيل هوية View، لذا أنواع المعدّلات المختلفة تنشئ دائمًا هويات جديدة، حتى لو كانت النتيجة البصرية متطابقة.

.modifier() vs المعدّلات المدمجة: مقارنة

المعدّلات المدمجة في SwiftUI هي methods امتداد مُعلَنة في بروتوكول View. كل معدّل مدمج (font, foregroundColor, padding) له تطبيقه الداخلي الخاص المُحسَّن من Apple. لا تستخدم بروتوكول ViewModifier ولا تُستدعى عبر .modifier().

الخاصية.modifier()المعدّلات المدمجة
البروتوكولViewModifierMethods امتداد View
إعادة الاستخدامأي عدد من المراتتتطلب تكرار الكود
الوسم (Parameterization)عبر المُهيئ (initializer)معاملات ثابتة
التجميعمعدّلات متعددة في واحدكل على حدة
الأداءمماثلأقصى

متى تستخدم .modifier(): عندما تُطبّق نفس تركيبة المعدّلات في عدة أماكن من التطبيق. هذا يوفر مصدرًا وحيدًا للحقيقة (single source of truth) للنمط ويُبسّط إعادة الهيكلة. متى تستخدم المعدّلات المباشرة: للتطبيقات لمرة واحدة الخاصة بـ View معينة.

وفقًا لـ Objc.io (2023)، فرق الأداء بين .modifier() وسلسلة من المعدّلات المدمجة لا يُذكر إحصائيًا (أقل من 1% من وقت التقديم). يجب أن يُحدد الاختيار بقابلية القراءة وإعادة الاستخدام، وليس بالأداء.

التطبيق الشرطي لـ .modifier()

التطبيق الشرطي لمعدّل هو مهمة شائعة في SwiftUI. النهج المعياري عبر المعامل الثلاثي (ternary operator) لا يعمل مع .modifier() لأن أنواع المعدّلات المختلفة تؤدي إلى أنواع ModifiedContent مختلفة.

swift
// ❌ لا يُجمَّع — أنواع معدّل مختلفة:
var body: some View {
    Text("شرطي")
        .modifier(isActive ? HighlightStyle() : DefaultStyle())
}

// ✅ صحيح: if/else داخل @ViewBuilder:
@ViewBuilder
var body: some View {
    if isActive {
        Text("شرطي").modifier(HighlightStyle())
    } else {
        Text("شرطي").modifier(DefaultStyle())
    }
}

// ✅ أو معدّل بمعامل:
struct ConditionalStyle: ViewModifier {
    let isActive: Bool

    func body(content: Content) -> some View {
        content
            .foregroundColor(isActive ? .blue : .gray)
            .opacity(isActive ? 1.0 : 0.5)
    }
}

Text("شرطي").modifier(ConditionalStyle(isActive: isActive))

توصية: للشروط البسيطة (إظهار/إخفاء، تغيير لون) استخدم معدّلًا بمعامل. للمنطق الشرطي المعقّد مع مجموعات معدّلات مختلفة — استخدم if/else داخل @ViewBuilder. النهج الثاني أكثر قابلية للقراءة لكنه قد يؤدي لتكرار الكود.

تسلسل وتكوين المعدّلات

تسلسل المعدّلات هو تتابع استدعاءات .modifier() والمعدّلات المدمجة المُطبَّقة على View واحدة. كل استدعاء ينشئ طبقة غلاف جديدة، وتتحد كل الطبقات في نوع View واحد عبر العموميات المتداخلة (nested generics).

يستخدم SwiftUI نظام أنواع لتمثيل سلسلة المعدّلات. على سبيل المثال، Text().font(.title).padding() له النوع ModifiedContent<ModifiedContent<Text, _FontModifier>, _PaddingLayout>. لكل معدّل مدمج هيكل معدّل داخلي خاص مخفي عن المطوّر.

مشكلة النوع: التداخل العميق لأنواع ModifiedContent يُبطئ التجميع ويُعقّد رسائل الأخطاء. ViewModifier المخصصة تسمح بـ«طي» عدة طبقات في طبقة واحدة، مما يُبسّط النوع الناتج ويُحسّن سرعة التجميع. وفقًا لـ Swift Compiler Team (2024)، استبدال 5–7 معدّلات متتالية بـ ViewModifier واحد يُقلّص وقت التجميع بنسبة 10–20% لـ Views المعقّدة.

قاعدة عملية: إذا كانت View تستخدم أكثر من 8 معدّلات — استخرج جزءًا منها إلى ViewModifier مخصص. هذا سيُسرّع التجميع ويُحسّن قابلية القراءة.

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

ماذا يفعل .modifier() في SwiftUI؟

.modifier() يطبّق ViewModifier مخصصًا على View، مُعيدًا ModifiedContent. هذه هي الطريقة الرئيسية لاستخدام المعدّلات المخصصة المُنشأة عبر بروتوكول ViewModifier، وبديل عن التسلسل المباشر للمعدّلات المدمجة.

كيف يختلف .modifier() عن المعدّلات المدمجة؟

.modifier() يستقبل نسخة من بروتوكول ViewModifier، مما يسمح بتغليف أي تركيبة من التغييرات. المعدّلات المدمجة (font, padding) هي methods امتداد View بمنطق ثابت. فرق الأداء ضئيل؛ الاختيار يُحدد بإعادة الاستخدام.

هل يمكن استخدام .modifier() بشكل شرطي؟

نعم، عبر if/else داخل @ViewBuilder أو عبر معدّل بمعامل منطقي (boolean). المعامل الثلاثي المباشر لا يعمل بسبب اختلاف أنواع ModifiedContent. يُنصح بالنهج القائم على المعامل للشروط البسيطة و if/else للمنطق المعقّد.

كيف يؤثر ترتيب .modifier() على النتيجة؟

تُطبّق المعدّلات من الخارج إلى الداخل: أول .modifier() يغلف View من الخارج، والتالية فوقه. الترتيب مهم للنتيجة البصرية، خاصة عند العمل مع overlay وpadding وframe.

هل يؤثر .modifier() على الأداء؟

التأثير لا يُذكر إحصائيًا (أقل من 1% من وقت التقديم). علاوة على ذلك، تجميع عدة معدّلات في ViewModifier واحد يمكن أن يُحسّن الأداء بتقليل عدد طبقات ModifiedContent وتبسيط النوع للمحسّن (compiler).

الخلاصة

  • .modifier() — method لتطبيق ViewModifier مخصص على View
  • ModifiedContent — النوع الناتج الذي يربط View والمعدّل
  • المعدّلات المدمجة — methods امتداد View غير مرتبطة بـ ViewModifier
  • المعدّلات المخصصة مُبررة عند التكرار في 3+ أماكن
  • التطبيق الشرطي — عبر if/else أو معدّل بمعامل
  • ترتيب المعدّلات يؤثر على النتيجة البصرية
  • التجميع في ViewModifier واحد يُسرّع التجميع بنسبة 10–20%

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

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

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

اقرأ أيضًا