.modifier() — متدی از پروتکل View در SwiftUI است که یک نمونه سفارشی ViewModifier را به هر نوع View اعمال میکند. بر اساس Apple Developer Documentation, 2024، این متد ViewModifier را میپذیرد و ModifiedContent را برمیگرداند و View اصلی را در یک نسخه اصلاحشده میپیچد. برخلاف اصلاحکنندههای داخلی که متدهای توسعه با پارامترهای ثابت هستند، .modifier() امکان استفاده از هر منطق سفارشی را که در نوعی پیادهسازیکننده پروتکل ViewModifier محصور شده است، فراهم میکند.
نکات اصلی
.modifier() — متدی است که در پروتکل View اعلام شده: func modifier<M: ViewModifier>(_ modifier: M) -> ModifiedContent<Self, M>. این متد نمونهای از نوع پیادهسازیکننده ViewModifier را میپذیرد و View اصلاحشدهای را که در نوع ModifiedContent پیچیده شده است، برمیگرداند.
این متد در iOS 13 ظاهر شد و روش اصلی اعمال اصلاحکنندههای سفارشی در SwiftUI است. برخلاف اصلاحکنندههای داخلی (font, foregroundColor, frame) که مستقیماً روی View فراخوانی میشوند، .modifier() نیاز به ایجاد قبلی نوع-اصلاحکننده دارد. این یک سطح انتزاع اضافه میکند، اما امکاناتی برای استفاده مجدد و پارامترسازی باز میکند.
بر اساس Hacking with Swift (2024)، .modifier() در هر پروژه SwiftUI که نیاز به سبک یکپارچه برای عناصر UI تکراری دارد، استفاده میشود. این متد در مقایسه با زنجیره اصلاحکنندههای داخلی سربار اضافهای ندارد — کامپایلر فراخوانی را بهینه میکند.
متد modifier یک پارامتر جنریک M را میپذیرد که توسط پروتکل ViewModifier محدود شده است. به لطف جنریکها، کامپایلر نوع خاص اصلاحکننده را میداند و میتواند نوع View حاصل را بدون پاک کردن نوع (type erasure) بهینه کند.
متد modifier(_:) یک نمونه ModifiedContent ایجاد میکند که View اصلی (Self) را با اصلاحکننده ارسالشده (M) پیوند میدهد. هنگام رندر، 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 برای تعیین تغییرات در سلسلهمراتب ModifiedContent استفاده میکند. نوع اصلاحکننده (M) در شکلدهی identity View شرکت میکند، بنابراین انواع مختلف اصلاحکنندهها همیشه identity جدید ایجاد میکنند، حتی اگر نتیجه بصری یکسان باشد.
اصلاحکنندههای داخلی SwiftUI — متدهای توسعهای هستند که در پروتکل View اعلام شدهاند. هر اصلاحکننده داخلی (font, foregroundColor, padding) پیادهسازی داخلی خاص خود را دارد که توسط اپل بهینه شده است. آنها از پروتکل ViewModifier استفاده نمیکنند و از طریق .modifier() فراخوانی نمیشوند.
| ویژگی | .modifier() | اصلاحکنندههای داخلی |
|---|---|---|
| پروتکل | ViewModifier | متدهای توسعه View |
| استفاده مجدد | هر تعداد بار | نیاز به تکرار کد |
| پارامترسازی | از طریق مقداردهنده اولیه | پارامترهای ثابت |
| گروهبندی | چندین اصلاحکننده در یکی | هر کدام جداگانه |
| عملکرد | قابل مقایسه | حداکثر |
چه زمانی از .modifier() استفاده کنیم: وقتی یک ترکیب از اصلاحکنندهها در چندین جای برنامه اعمال میشود. این یک منبع واحد حقیقت برای سبک فراهم میکند و بازسازی کد را ساده میکند. چه زمانی از اصلاحکنندههای مستقیم استفاده کنیم: برای کاربردهای یکبار مصرف خاص برای یک View خاص.
بر اساس Objc.io (2023)، تفاوت عملکرد بین .modifier() و زنجیره اصلاحکنندههای داخلی از نظر آماری ناچیز است (کمتر از 1٪ زمان رندر). انتخاب باید بر اساس خوانایی و قابلیت استفاده مجدد تعیین شود، نه عملکرد.
اعمال شرطی اصلاحکننده — یکی از وظایف رایج در SwiftUI است. رویکرد استاندارد از طریق عملگر سهتایی با .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 واحد ترکیب میشوند.
SwiftUI از سیستم نوع برای نمایش زنجیره اصلاحکنندهها استفاده میکند. به عنوان مثال، Text().font(.title).padding() دارای نوع ModifiedContent<ModifiedContent<Text, _FontModifier>, _PaddingLayout> است. هر اصلاحکننده داخلی ساختار-اصلاحکننده داخلی خود را دارد که از توسعهدهنده پنهان است.
مشکل نوع: تودرتویی عمیق انواع ModifiedContent کامپایل را کند میکند و پیامهای خطا را پیچیده میکند. ViewModifier سفارشی امکان «جمع کردن» چند لایه در یک لایه را فراهم میکند و نوع حاصل را ساده میکند و سرعت کامپایل را بهبود میبخشد. بر اساس Swift Compiler Team (2024)، جایگزینی 5–7 اصلاحکننده متوالی با یک ViewModifier زمان کامپایل را برای Viewهای پیچیده 10–20٪ کاهش میدهد.
قاعده عملی: اگر View از بیش از 8 اصلاحکننده استفاده میکند — بخشی را به یک ViewModifier سفارشی منتقل کنید. این کار کامپایل را سرعت میبخشد و خوانایی را بهبود میدهد.
سوالات متداول
.modifier() یک ViewModifier سفارشی را به View اعمال میکند و ModifiedContent را برمیگرداند. این روش اصلی استفاده از اصلاحکنندههای کاربر ایجاد شده از طریق پروتکل ViewModifier و جایگزینی برای زنجیرههای مستقیم اصلاحکنندههای داخلی است.
.modifier() نمونهای از پروتکل ViewModifier را میپذیرد و امکان محصور کردن هر ترکیبی از تغییرات را فراهم میکند. اصلاحکنندههای داخلی (font, padding) — متدهای توسعه View با منطق ثابت هستند. تفاوت عملکرد حداقل است، انتخاب بر اساس استفاده مجدد تعیین میشود.
بله، از طریق if/else درون @ViewBuilder یا از طریق اصلاحکننده با پارامتر بولی. عملگر سهتایی مستقیم به دلیل انواع مختلف ModifiedContent کار نمیکند. رویکرد با پارامتر برای شرایط ساده و if/else برای منطق پیچیده توصیه میشود.
اصلاحکنندهها از بیرونی به درونی اعمال میشوند: اولین .modifier() View را از بیرون میپیچد، بعدیها — روی آن. ترتیب بر نتیجه بصری تأثیر میگذارد، به ویژه هنگام کار با overlay، padding و frame.
تأثیر از نظر آماری ناچیز است (کمتر از 1٪ زمان رندر). علاوه بر این، گروهبندی چند اصلاحکننده در یک ViewModifier میتواند عملکرد را بهبود بخشد، تعداد لایههای ModifiedContent را کاهش داده و نوع را برای کامپایلر ساده کند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید