الأنماط المعمارية في Swift: MVC و MVVM و VIPER مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الأنماط المعمارية في Swift: من الفوضى إلى النظام

\n\n

كل مطور iOS يواجه عاجلاً أم آجلاً السؤال: "كيف أنظم الكود بحيث لا يتحول المشروع إلى فوضى بعد ستة أشهر؟" الإجابة بسيطة — الأنماط المعمارية. في Swift، كما في أي لغة أخرى، يحدد اختيار البنية مدى سهولة صيانة التطبيق واختباره وتوسيعه. اليوم سنحلل ثلاثة من أشهر الأساليب: MVC و MVVM و VIPER. لا نظرية جافة — فقط كود حي ونصائح عملية.

\n\n

إذا كنت تكتب بلغة Swift ولكنك لا تزال تستخدم "كل شيء في ملف واحد" — فهذه المقالة لك. هيا بنا!

\n\n

MVC (Model-View-Controller) — الكلاسيكية

\n\n

MVC هو النمط الذي تضعه Apple كأساس لـ UIKit. يبدو الأمر بسيطًا: Model مسؤول عن البيانات، View مسؤول عن العرض، Controller يربط بينهما. لكن عمليًا، يتحول MVC في iOS غالبًا إلى Massive View Controller — وحدة تحكم تعرف كل شيء، تفعل كل شيء، وتزن آلاف الأسطر.

\n\n

ومع ذلك، إذا تم الالتزام بالانضباط، فإن MVC يعمل بشكل ممتاز. إليك مثال لتطبيق بسيط لعرض قائمة المستخدمين.

\n\n
// Model\nstruct User {\n    let name: String\n    let email: String\n}\n\n// View (ليس كود UI، بل بروتوكول للتحديث)\nprotocol UserListView: AnyObject {\n    func showUsers(_ users: [User])\n    func showError(_ error: Error)\n}\n\n// Controller\nclass UserListViewController: UIViewController, UserListView {\n    \n    @IBOutlet weak var tableView: UITableView!\n    private var users: [User] = []\n    private let dataService = DataService()\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        tableView.dataSource = self\n        loadUsers()\n    }\n    \n    func loadUsers() {\n        dataService.fetchUsers { [weak self] result in\n            switch result {\n            case .success(let users):\n                self?.showUsers(users)\n            case .failure(let error):\n                self?.showError(error)\n            }\n        }\n    }\n    \n    func showUsers(_ users: [User]) {\n        self.users = users\n        tableView.reloadData()\n    }\n    \n    func showError(_ error: Error) {\n        let alert = UIAlertController(title: "خطأ", message: error.localizedDescription, preferredStyle: .alert)\n        alert.addAction(UIAlertAction(title: "موافق", style: .default))\n        present(alert, animated: true)\n    }\n}\n\nextension UserListViewController: UITableViewDataSource {\n    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n        return users.count\n    }\n    \n    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n        let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath)\n        let user = users[indexPath.row]\n        cell.textLabel?.text = user.name\n        cell.detailTextLabel?.text = user.email\n        return cell\n    }\n}
\n\n

إيجابيات MVC:

\n
    \n
  • البساطة والوضوح — كل مطور جديد يفهمه بسرعة.
  • \n
  • دعم أصلي من Apple — لا حاجة لإضافة مكتبات خارجية.
  • \n
  • بداية سريعة للمشاريع الصغيرة.
  • \n
\n\n

سلبيات MVC:

\n
    \n
  • تصبح وحدات التحكم "ضخمة" ويصعب اختبارها.
  • \n
  • صعوبة إعادة استخدام المنطق بين الشاشات المختلفة.
  • \n
  • عند نمو المشروع، يتحول الكود إلى معكرونة.
  • \n
\n\n

الخلاصة: MVC جيد للتطبيقات البسيطة أو النماذج الأولية. إذا كنت تعلم أن المشروع سينمو — فانظر نحو MVVM أو VIPER.

\n\n

MVVM (Model-View-ViewModel) — المعيار الحديث

\n\n

يحل MVVM المشكلة الرئيسية لـ MVC — يخفف الحمل عن وحدة التحكم. يتم نقل كل منطق الأعمال وإعداد البيانات للعرض إلى ViewModel. View (وحدة التحكم) تشترك فقط في التغييرات

المدونات

توصيات الكتب