نمط MVVM
افصل مسؤوليات العرض ونموذج العرض والنموذج.
نمط MVVM درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.
ما المقصود بـ MVVM؟
اختصار MVVM هو Model-View-ViewModel. وهو نمط معماري يقسّم تطبيقك إلى ثلاث طبقات، لكل منها مسؤولية واضحة واحدة.
- Model — البيانات وقواعد العمل
- View — ما يراه المستخدم
- ViewModel — الجسر الذي يجهّز بيانات Model لـ View
الهدف هو فصل المسؤوليات؛ إذ تتغيّر كل طبقة لسبب يخصّها، بصورة مستقلة عن الطبقات الأخرى.
طبقة Model
تحتوي Model على بياناتك الخام والقواعد التي تحكمها. ولا تعرف شيئًا عن الشاشة أو عن طريقة عرض العناصر.
تكون Models عادةً عبارة عن هياكل بسيطة أو كائنات من النطاق. ويسهل اختبارها لأنها لا تعتمد على واجهة المستخدم.
struct User {
let id: UUID
let firstName: String
let lastName: String
let isPremium: Bool
}
struct Order {
let items: [String]
let total: Decimal
}طبقة View
تتولى View العرض فقط. ففي SwiftUI تكون عبارة عن هياكل View، وفي UIKit تكون عبارة عن UIViewController والعروض الفرعية التابعة له.
لا تحتوي View الجيدة على أي منطق خاص بالعمل. فهي تعرض الحالة فقط، وتمرّر إجراءات المستخدم إلى ViewModel.
struct ProfileView: View {
@StateObject var viewModel: ProfileViewModel
var body: some View {
VStack {
Text(viewModel.displayName)
if viewModel.showBadge {
Text("Premium")
}
}
}
}طبقة ViewModel
تقع ViewModel بين Model وView. فهي تأخذ بيانات Model الخام وتحولها إلى قيم جاهزة للعرض يمكن لـ View عرضها مباشرة.
كما تكشف عن النوايا (الأساليب) التي تستدعيها View عندما يتفاعل المستخدم.
final class ProfileViewModel: ObservableObject {
@Published var displayName: String
@Published var showBadge: Bool
init(user: User) {
displayName = user.firstName + " " + user.lastName
showBadge = user.isPremium
}
}لماذا نفصل المسؤوليات؟
عندما تختلط عملية التنسيق والشبكات والعرض داخل view controller، يتحول ذلك الملف إلى كتلة ضخمة يتعذر اختبارها.
وبتقسيم المسؤوليات:
- يمكن إعادة استخدام Model عبر شاشات متعددة
- يمكن اختبار ViewModel باختبارات وحدات من دون واجهة مستخدم
- تبقى View صغيرة وتصريحية
ما الذي ينتمي إلى Model؟
ضع في Model:
- كيانات النطاق (
User،Product) - قواعد التحقق الخاصة بالعمل
- تجريدات التخزين والشبكات (غالبًا عبر خدمات تستدعيها ViewModel)
لا تضع أبدًا نصوص واجهة المستخدم أو الألوان أو التنسيق في Model.
ما الذي ينتمي إلى ViewModel؟
تتعامل ViewModel مع منطق العرض:
- تنسيق التواريخ والعملات والأسماء في سلاسل نصية للعرض
- تحديد حالات واجهة المستخدم الظاهرة (التحميل، والخطأ، والفراغ)
- تنسيق استدعاءات الخدمات وكشف النتائج
final class CartViewModel: ObservableObject {
@Published var totalText: String = ""
func update(with order: Order) {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
totalText = formatter.string(from: order.total as NSNumber) ?? "-"
}
}ما الذي ينتمي إلى View؟
يجب أن تقتصر View على:
- ترتيب عناصر واجهة المستخدم وعرضها
- قراءة الحالة المنشورة من ViewModel
- تمرير النقرات والإيماءات باستدعاء أساليب ViewModel
إذا وجدت if يقرر قواعد العمل داخل View، فمن المرجح أن ينتمي ذلك المنطق إلى ViewModel.
تدفق البيانات في MVVM
يتدفق البيانات في اتجاه واحد، بينما تتدفق الإجراءات في الاتجاه المعاكس:
- Model -> ViewModel -> View للبيانات
- View -> ViewModel لنوايا المستخدم
لا تتحدث View مع Model مباشرةً. ويحافظ ذلك على توجّه الاعتماديات إلى الداخل، نحو نطاقك.
MVVM في مقابل MVC
في MVC التقليدي، يكبر حجم controller غالبًا لأنه يتولى التنسيق والشبكات وربط الواجهة كلها في الوقت نفسه.
يستخرج MVVM منطق العرض هذا إلى ViewModel، تاركًا controller (أو View في SwiftUI) نحيفًا. كما أن ViewModel لا تعتمد على إطار واجهة المستخدم، ولذلك يسهل اختبارها كثيرًا.
جزء متكامل
إليك جزءًا صغيرًا لكنه متكامل من MVVM يربط الطبقات معًا.
struct Account { let balance: Decimal }
final class AccountViewModel: ObservableObject {
@Published var balanceText: String
init(account: Account) {
balanceText = "$" + "\(account.balance)"
}
}
struct AccountView: View {
@StateObject var viewModel: AccountViewModel
var body: some View { Text(viewModel.balanceText) }
}مراجعة سريعة
اختبر فهمك لمسؤوليات MVVM.
مراجعة
تعلّمت الطبقات الثلاث في MVVM وحدود مسؤولياتها:
- Model — البيانات الخام وقواعد العمل، من دون واجهة مستخدم
- ViewModel — منطق العرض والنوايا
- View — عرض حالة ViewModel فقط
إن إبقاء هذه المسؤوليات منفصلة يجعل شيفرتك قابلة للاختبار وإعادة الاستخدام، ويسهّل فهمها. سنربط في الخطوة التالية ViewModel بـ View باستخدام الارتباطات.
الأسئلة الشائعة
هل درس «نمط MVVM» مجاني؟
نعم — نص درس «نمط MVVM» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «نمط MVVM»؟
افصل مسؤوليات العرض ونموذج العرض والنموذج. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «نمط MVVM»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.