.modifier() هو method من بروتوكول View في SwiftUI يطبّق نسخة مخصصة من ViewModifier على أي نوع View. وفقًا لـ Apple Developer Documentation, 2024، يستقبل method ViewModifier ويعيد ModifiedContent، ليغلف View الأصلية في نسخة معدّلة. على عكس المعدّلات المدمجة، وهي methods امتداد بمعاملات ثابتة، يسمح .modifier() باستخدام أي منطق مخصص مغلف في نوع يطبّق بروتوكول ViewModifier.
النقاط الرئيسية
.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(_:) ينشئ نسخة ModifiedContent تربط View الأصلية (Self) بالمعدّل المُمرَر (M). أثناء التقديم (rendering)، يستدعي SwiftUI M.body(content: self)، مُمرِرًا View الأصلية كمعامل content.
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، لذا أنواع المعدّلات المختلفة تنشئ دائمًا هويات جديدة، حتى لو كانت النتيجة البصرية متطابقة.
المعدّلات المدمجة في SwiftUI هي methods امتداد مُعلَنة في بروتوكول View. كل معدّل مدمج (font, foregroundColor, padding) له تطبيقه الداخلي الخاص المُحسَّن من Apple. لا تستخدم بروتوكول ViewModifier ولا تُستدعى عبر .modifier().
| الخاصية | .modifier() | المعدّلات المدمجة |
|---|---|---|
| البروتوكول | ViewModifier | Methods امتداد View |
| إعادة الاستخدام | أي عدد من المرات | تتطلب تكرار الكود |
| الوسم (Parameterization) | عبر المُهيئ (initializer) | معاملات ثابتة |
| التجميع | معدّلات متعددة في واحد | كل على حدة |
| الأداء | مماثل | أقصى |
متى تستخدم .modifier(): عندما تُطبّق نفس تركيبة المعدّلات في عدة أماكن من التطبيق. هذا يوفر مصدرًا وحيدًا للحقيقة (single source of truth) للنمط ويُبسّط إعادة الهيكلة. متى تستخدم المعدّلات المباشرة: للتطبيقات لمرة واحدة الخاصة بـ View معينة.
وفقًا لـ Objc.io (2023)، فرق الأداء بين .modifier() وسلسلة من المعدّلات المدمجة لا يُذكر إحصائيًا (أقل من 1% من وقت التقديم). يجب أن يُحدد الاختيار بقابلية القراءة وإعادة الاستخدام، وليس بالأداء.
التطبيق الشرطي لمعدّل هو مهمة شائعة في SwiftUI. النهج المعياري عبر المعامل الثلاثي (ternary operator) لا يعمل مع .modifier() لأن أنواع المعدّلات المختلفة تؤدي إلى أنواع ModifiedContent مختلفة.
// ❌ لا يُجمَّع — أنواع معدّل مختلفة:
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() يطبّق ViewModifier مخصصًا على View، مُعيدًا ModifiedContent. هذه هي الطريقة الرئيسية لاستخدام المعدّلات المخصصة المُنشأة عبر بروتوكول ViewModifier، وبديل عن التسلسل المباشر للمعدّلات المدمجة.
.modifier() يستقبل نسخة من بروتوكول ViewModifier، مما يسمح بتغليف أي تركيبة من التغييرات. المعدّلات المدمجة (font, padding) هي methods امتداد View بمنطق ثابت. فرق الأداء ضئيل؛ الاختيار يُحدد بإعادة الاستخدام.
نعم، عبر if/else داخل @ViewBuilder أو عبر معدّل بمعامل منطقي (boolean). المعامل الثلاثي المباشر لا يعمل بسبب اختلاف أنواع ModifiedContent. يُنصح بالنهج القائم على المعامل للشروط البسيطة و if/else للمنطق المعقّد.
تُطبّق المعدّلات من الخارج إلى الداخل: أول .modifier() يغلف View من الخارج، والتالية فوقه. الترتيب مهم للنتيجة البصرية، خاصة عند العمل مع overlay وpadding وframe.
التأثير لا يُذكر إحصائيًا (أقل من 1% من وقت التقديم). علاوة على ذلك، تجميع عدة معدّلات في ViewModifier واحد يمكن أن يُحسّن الأداء بتقليل عدد طبقات ModifiedContent وتبسيط النوع للمحسّن (compiler).
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.