View Protocol — پروتکل بنیادین SwiftUI است که هر مؤلفه بصری رابط کاربری باید با آن مطابقت داشته باشد. به گفته Apple Developer Documentation, 2024، View یک قرارداد واحد تعریف میکند: ساختار یا کلاسی که این پروتکل را پیادهسازی میکند باید ویژگی محاسباتی body را ارائه دهد. SwiftUI از طریق این پروتکل کل سلسلهمراتب صفحهها را از برچسبهای متنی ساده تا ساختارهای پیچیده ناوبری میسازد.
نکات کلیدی
View Protocol — پروتکل مرکزی SwiftUI است که تعیین میکند هر عنصر بصری چگونه محتوای خود را توصیف میکند. برخلاف UIKit که در آن هر عنصر از طریق کلاسها از UIView ارثبری میکند، SwiftUI از رویکرد پروتکلمحور استفاده میکند: هر نوعی که با پروتکل View مطابقت داشته باشد میتواند روی صفحه نمایش داده شود.
پروتکل View نیاز به پیادهسازی یک ویژگی محاسباتی به نام body دارد که محتوایی را برمیگرداند. اما در پس این سادگی، یک سیستم ترکیببندی قدرتمند نهفته است: body میتواند هر نوع منطبق با View را برگرداند، شامل انواع ابتدایی (Text, Image, Button)، ظروف (VStack, HStack, ZStack) و مؤلفههای ترکیبی سفارشی.
طبق WWDC 2023، بیش از ۹۵٪ از تمام صفحههای برنامههای SwiftUI از طریق ترکیب ساختارهایی که پروتکل View را پیادهسازی میکنند ساخته میشوند. این امر View Protocol را به پایه و اساس کل معماری SwiftUI تبدیل میکند.
SwiftUI نیاز دارد که View یک value type (ساختار، struct) باشد نه یک کلاس. این یک تصمیم معماری کلیدی است: value types دارای طول عمر قابل پیشبینی هستند، حالت تغییرپذیر مشترک ندارند و به SwiftUI اجازه میدهند به طور مؤثر تشخیص دهد کدام بخشهای سلسلهمراتب تغییر کرده و نیاز به بازترسیم دارند.
اگر سعی کنید View را به عنوان کلاس بسازید، کامپایلر خطا میدهد: پروتکل View از پروتکل DynamicViewProperty ارثبری میکند که نیاز به value semantics دارد. کلاسها میتوانند با View مطابقت داشته باشند، اما این رویکرد اصطلاحی را نقض میکند و مزایای بهروزرسانی خودکار را از بین میبرد.
body — تنها الزام اجباری پروتکل View است. این یک ویژگی محاسباتی است که محتوای نمایش داده شده روی صفحه را برمیگرداند. نوع مقدار بازگشتی — some View، به معنای «نوع خاصی منطبق با View که توسط کامپایلر تعیین میشود».
struct GreetingView: View {
var name: String
var body: some View {
VStack {
Text("سلام، \(name)!")
.font(.title)
.foregroundColor(.blue)
Button("شروع") {
print("دکمه فشرده شد")
}
}
}
}
body چگونه کار میکند: SwiftUI هر زمان که وضعیت برنامه تغییر کند و نیاز به بازترسیم باشد، body را فراخوانی میکند. فریمورک درخت View جدید را با قدیمی مقایسه میکند و فقط تغییرات لازم را اعمال میکند (diffing). این یک رویکرد کاملاً اعلامی است — شما توصیف میکنید چه چیزی نمایش داده شود، و SwiftUI مراقب نحوه پیادهسازی آن است.
یک جزئیات مهم: body نباید عوارض جانبی داشته باشد. در طول عمر برنامه多次 فراخوانی میشود، و اگر درون body وضعیت خارجی تغییر کند — این منجر به رفتار غیرقابل پیشبینی میشود. برای عوارض جانبی از task، onChange یا DispatchQueue استفاده کنید.
SwiftUI محدودیتی اعمال میکند: body فقط میتواند یک عنصر ریشه برگرداند. اگر نیاز به نمایش چندین عنصر در یک سطح دارید، آنها را در یک ظرف — VStack، HStack، ZStack یا Group قرار دهید. با ظهور @ViewBuilder این محدودیت کمتر محسوس شده است، اما از نظر مفهومی body همیشه یک View برمیگرداند.
some View — این نحو نوع نیمهشفاف (opaque type) است که در Swift 5.1 به طور خاص برای SwiftUI معرفی شد. به این معنی که تابع یا ویژگی یک نوع خاص منطبق با پروتکل View را برمیگرداند، اما کد فراخواننده نمیداند و نباید بداند که دقیقاً چه نوعی برگردانده میشود.
کامپایلر Swift نوع خاص را در مرحله کامپایل برای هر پیادهسازی body تعیین میکند، اما آن را از دنیای خارج پنهان میکند. این به SwiftUI اجازه میدهد سلسلهمراتب View را با دانستن انواع دقیق همه مؤلفهها بهینهسازی کند، اما به توسعهدهنده انعطافپذیری در تغییر پیادهسازی بدون تغییر امضا میدهد.
struct ContentView: View {
var body: some View {
Text("سلام، دنیا!") // کامپایلر میداند این Text است
}
}
چرا some View و نه فقط View؟ اگر body صرفاً View (به عنوان پروتکل) برمیگرداند، SwiftUI نمیتوانست نوع خاص را در زمان کامپایل تعیین کند. این منجر به سربار اضافی برای بستهبندی در کانتینر وجودی (existential container) میشود. some View اطلاعات کافی برای بهینهسازی در اختیار کامپایلر قرار میدهد و در عین حال انعطافپذیری پروتکل را حفظ میکند.
محدودیت اصلی — body باید یک نوع واحد را برگرداند. نمیتوان در یک شاخه شرط Text و در شاخه دیگر Image را بدون کلاسهای واسط خاص (AnyView, Group, یا @ViewBuilder) برگرداند. کامپایلر این را در مرحله کامپایل بررسی میکند: تمام مسیرهای بازگشتی ممکن باید نوع یکسانی داشته باشند.
برای دور زدن این محدودیت از @ViewBuilder (نوع TupleView واحد ایجاد میکند)، Group (که همچنین نوع واحد برمیگرداند) یا AnyView (نوع را پاک میکند اما سربار اضافه میکند) استفاده میشود. AnyView فقط زمانی باید استفاده شود که گزینههای دیگر ممکن نباشند، زیرا بهینهسازیهای SwiftUI را غیرفعال میکند.
@ViewBuilder — یک result builder است که حاشیهنویسی آن امکان ترکیب چندین View را در یک ترکیب واحد بدون ظروف تو در تو فراهم میکند. @ViewBuilder به طور خودکار چندین عبارت را در یک چندتایی (TupleView) میپیچد یا منطق شرطی (If / else / switch) را با نوع بازگشتی صحیح اعمال میکند.
struct DashboardView: View {
var isLoggedIn: Bool
@ViewBuilder
var body: some View {
if isLoggedIn {
Text("خوش آمدید!")
.font(.largeTitle)
ProfileCard()
} else {
LoginButton()
.padding()
}
}
}
@ViewBuilder چگونه کار میکند: کامپایلر هر بلوک کد درون @ViewBuilder را به فراخوانیهای متدهای استاتیک buildBlock، buildEither، buildOptional و غیره تبدیل میکند. اگر بلوک شامل چندین عبارت باشد — آنها در TupleView پیچیده میشوند. اگر بلوک شامل منطق شرطی باشد — کامپایلر ConditionalContent تولید میکند که نوع شاخه را پنهان میکند.
@ViewBuilder محدودیتی اعمال میکند: تا ۱۰ عنصر در یک بلوک (محدودیت TupleView). اگر نیاز به جمعآوری بیش از ده عنصر دارید، از Group، ForEach استفاده کنید یا به زیرمؤلفهها تقسیم کنید. این محدودیت به این دلیل وجود دارد که Swift یک overload جداگانه buildBlock برای هر اریتی از ۱ تا ۱۰ تولید میکند.
ترکیب — اصل کلیدی SwiftUI: رابطهای پیچیده از مؤلفههای View کوچک و قابل استفاده مجدد ساخته میشوند. هر مؤلفه پروتکل View را پیادهسازی میکند و مسئول بخش خود از صفحه است. اصلاحکنندهها (font, padding, foregroundColor) روی View اعمال میشوند و یک View جدید با تنظیمات تغییر یافته برمیگردانند.
اصلاحکنندهها در SwiftUI جهش نیستند، بلکه ایجاد یک لایه جدید در اطراف View اصلی هستند. هر اصلاحکننده یک نوع جدید (ModifiedContent) برمیگرداند که به SwiftUI اجازه میدهد درخت اصلاحکنندهها بسازد و فقط بخشهای تغییر یافته را به طور مؤثر بازترسیم کند. ترتیب اعمال اصلاحکنندهها اهمیت دارد: ترتیبهای مختلف نتایج بصری متفاوتی میدهند.
Text("سلام، SwiftUI!")
.font(.title) // ModifiedContent
.padding() // ModifiedContent<..., PaddingModifier>
.background(.yellow) // ModifiedContent<..., BackgroundModifier>
.cornerRadius(8) // ModifiedContent<..., CornerRadiusModifier>
بهینهسازی عملکرد: SwiftUI مقادیر مشخص View را مقایسه نمیکند، بلکه هویت آنها را از طریق مکانیزم identity (id, ForEach, هویت پایدار ساختارها) مقایسه میکند. اگر ساختار View تغییر نکرده باشد — body فراخوانی نمیشود. این از طریق مقایسه Equatable و مکانیزم PreferenceKey برای انتقال دادهها به بالای سلسلهمراتب به دست میآید.
برای ترکیب مؤثر، توصیه میشود صفحههای پیچیده را به زیرمؤلفههای مستقل تقسیم کنید، هر کدام با حداقل وضعیت خود. این به SwiftUI اجازه میدهد فقط بخشهای تغییر یافته سلسلهمراتب را بازترسیم کند، نه کل صفحه را.
سؤالات متداول
View Protocol — پروتکل پایه SwiftUI است که هر مؤلفه قابل نمایش باید با آن مطابقت داشته باشد. این پروتکل تنها یک ویژگی محاسباتی body را نیاز دارد که محتوا را برمیگرداند. همه عناصر استاندارد SwiftUI — Text, Button, Image, VStack — این پروتکل را پیادهسازی میکنند.
SwiftUI برای بهروزرسانی قابل پیشبینی رابط از value semantics استفاده میکند. ساختارها حالت تغییرپذیر مشترک ندارند که به SwiftUI اجازه میدهد سلسلهمراتب View قدیم و جدید را به طور مؤثر مقایسه کرده و فقط عناصر تغییر یافته را بازترسیم کند. کلاسها این بهینهسازی را نقض میکنند.
body some View برمیگرداند — نوع نیمهشفافی که پیادهسازی مشخص را پنهان میکند. در عمل هر نوع منطبق با View برگردانده میشود: Text, Image, VStack, ساختار سفارشی. کامپایلر نوع خاص را در مرحله کامپایل برای بهینهسازی تعیین میکند.
some View — نوع نیمهشفاف با تعیین نوع خاص در مرحله کامپایل. AnyView — پاک کردن نوع (type erasure) که هر View را در یک کانتینر واحد میپیچد. some View کارآمدتر است، AnyView سربار اضافه میکند و فقط زمانی استفاده میشود که تغییر نوع پویا نیاز باشد.
تا ۱۰ عنصر — این محدودیت TupleView است که buildBlock را برای اریتیهای ۱ تا ۱۰ تولید میکند. اگر عناصر بیشتری نیاز دارید، از Group، ForEach، List استفاده کنید یا به زیرمؤلفهها تقسیم کنید. این محدودیت در سطح کامپایلر Swift وجود دارد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید