不同架构的详细分析VIP架构
不同架构的详细分析
文章目录
传统的MVC架构
**传统的MVC架构将系统分成三个部分:模型(Model)、视图(View)和控制器(Controller)。**模型表示数据和数据处理逻辑;视图表示用户界面;控制器接收用户输入并处理真正的动作。该架构的优点是简单易懂,容易开发和维护;缺点是当应用规模变大时,会出现控制器臃肿、业务逻辑混杂的问题,不利于代码重用和维护。
MVVM架构
**MVVM架构将系统分成三个部分:视图(View)、视图模型(ViewModel)和模型(Model)。**视图负责渲染和用户输入;视图模型处理逻辑并更新视图;模型则与数据相关。通过数据绑定机制,视图模型可以直接将改变反映到视图中,从而实现了低耦合、高可复用性的特点。缺点是实现复杂,需要实现双向数据绑定,代码量相对较多。
VIPER架构
** VIPER架构将系统分为五个部分:视图(View)、表示器(Presenter)、交互器(Interactor)、实体(Entity)和路由(Router)。**表示器负责将用户的操作解析成交互器可执行的操作;交互器负责执行具体的业务逻辑并返回结果给表示器;实体存储实际的业务逻辑,路由负责模块之间的路由和导航。该架构实现了单一职责原则(SRP),代码复用性高,且易于维护。缺点是分层过于细致,代码量稍多,有一定的上手难度。
Clean Swift(也称为 VIP)架构
** Clean Swift将系统分为六个部分:视图控制器(ViewController)、表示器(Presenter)、业务逻辑处理器(Interactor)、实体(Entity)、请求(Request)和响应(Response)。**Clean Swift 原则上是 VIPER 的变种,该架构推崇单一责任原则(SRP),实现了职责分离的目标,同时保证代码的可测试性和可维护性。在 Clean Swift 中,视图控制器只负责管理界面的生命周期和 UI 事件的处理,而将实际业务逻辑和数据处理都放在表示器、业务逻辑处理器和实体等组件中。该架构优点是职责分层明确,代码简洁可读,易于阅读和维护;同时提供了统一的请求、响应和错误处理接口,有利于提高代码复用性和可测试性。缺点是需要遵循约定式的编程规范。
demo
以下是使用 Clean Swift 架构编写的一个简单的 To-do List 应用程序的 demo,其包括了添加、查看、编辑和删除待办事项等功能。
1. 创建 Xcode 工程
- 打开 Xcode。
- 创建一个新的 iOS App 项目,并命名为
ToDoListDemo
。 - 在项目设置中选择
Swift
语言和Storyboard
用户界面。
2. 创建架构文件和类
-
在 Xcode 中,创建几个 Group,用于存放 Clean Swift 架构中的各个部分,例如:
Models
、Networking
、Scene
等。 -
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListModels.swift
。在该文件中定义应用程序中使用的所有必要类型、结构体和模型。// 创建 TodoItem 结构体 struct TodoItem { var id: Int var title: String var description: String? var isCompleted: Bool var date: Date? } // 创建 TodoListViewModel 结构体 struct TodoListViewModel { var items: [TodoItem] }
-
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListWorker.swift
。该文件将包含执行网络请求和数据持久化的代码。protocol TodoListWorkerProtocol { func fetchItems(completion: ([TodoItem]) -> Void) func saveItem(_ item: TodoItem, completion: @escaping (Bool) -> Void) func deleteItem(_ item: TodoItem, completion: @escaping (Bool) -> Void) } class TodoListWorker: TodoListWorkerProtocol { func fetchItems(completion: ([TodoItem]) -> Void) { // 在此处执行网络请求或者数据持久化操作 // 返回获取到的 TodoItem 数据 } func saveItem(_ item: TodoItem, completion: @escaping (Bool) -> Void) { // 在此处执行网络请求或者数据持久化操作 completion(true) } func deleteItem(_ item: TodoItem, completion: @escaping (Bool) -> Void) { // 在此处执行网络请求或者数据持久化操作 completion(true) } }
-
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListInteractor.swift
。在该文件中创建操作TodoItem
的TodoListInteractor
接口,并提供TodoListInteractor
的默认实现。protocol TodoListInteractorProtocol { func fetchTodoList() func addTodoItem(item: TodoItem) // 添加更新和删除操作方法 } class TodoListInteractor: TodoListInteractorProtocol { var presenter: TodoListPresenterProtocol? var worker: TodoListWorkerProtocol? func fetchTodoList() { worker?.fetchItems(completion: { [weak self] items in self?.presenter?.presentFetchedTodoList(response: items) }) } func addTodoItem(item: TodoItem) { worker?.saveItem(item, completion: { [weak self] success in if success { self?.fetchTodoList() } }) } // 添加更新和删除操作方法的默认实现 }
-
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListPresenter.swift
。在该文件中创建表示获取到的TodoItem
和操作后的TodoListViewModel
的TodoListPresenter
接口,并提供TodoListPresenter
的默认实现。protocol TodoListPresenterProtocol { func presentFetchedTodoList(response: [TodoItem]) // 添加更新和删除操作方法 } class TodoListPresenter: TodoListPresenterProtocol { weak var viewController: TodoListViewControllerProtocol? func presentFetchedTodoList(response: [TodoItem]) { let viewModel = TodoListViewModel(items: response) viewController?.displayFetchedTodoList(viewModel: viewModel) } // 添加更新和删除操作方法的默认实现 }
-
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListViewController.swift
。在该文件中创建表示用户界面的TodoListViewController
和表示用户输入的TodoListViewControllerInput
接口,并提供TodoListViewController
的默认实现。protocol TodoListViewControllerProtocol: AnyObject { func displayFetchedTodoList(viewModel: TodoListViewModel) } protocol TodoListViewControllerInput { func displayAddTodoItemSuccess() // 添加更新和删除操作方法 } class TodoListViewController: UIViewController, TodoListViewControllerProtocol { var interactor: TodoListInteractorProtocol? var router: TodoListRouterProtocol? // 实现 viewDidLoad() 和其他方法 func displayFetchedTodoList(viewModel: TodoListViewModel) { // 更新用户界面以显示获取到的数据 } // 添加更新和删除操作的默认实现 }
-
在
Scene
Group 中,创建一个新的 Swift 文件,命名为ToDoListRouter.swift
。在该文件中创建表示导航逻辑的TodoListRouter
接口,并提供TodoListRouter
的默认实现。protocol TodoListRouterProtocol { func navigateToAddTodoItem() // 添加其他导航方法 } class TodoListRouter: TodoListRouterProtocol { weak var viewController: UIViewController? // 实现 TodoListRouterProtocol 中的方法 // 可以使用 NavigationController 或 Modal 方式实现不同的导航 }
3. 生成视图控制器并完成基本逻辑
-
在 Xcode 中创建一个新的
UIViewController
类,命名为ToDoListTableViewController
,并在故事板中设置它为启动界面。 -
使用 Interface Builder 创建显示
TodoItem
的列表,并进行相应的布局和设计。注意:在该部分中只包含了部分代码。完整代码可以在我的 GitHub 仓库中找到:
https://github.com/techsleep/clean-swift-todo-app-demo
。 -
在
ToDoListTableViewController.swift
文件中,声明并初始化interactor
、presenter
和router
。class ToDoListTableViewController: UITableViewController { var interactor: TodoListInteractorProtocol? var presenter: TodoListPresenterProtocol? var router: TodoListRouterProtocol? override func viewDidLoad() { super.viewDidLoad() interactor = TodoListInteractor() interactor?.presenter = presenter presenter = TodoListPresenter() presenter?.viewController = self router = TodoListRouter() router?.viewController = self interactor?.fetchTodoList() // 设置 NavigationController 样式和导航按钮等 } }
-
在
ToDoListTableViewController.swift
文件中,遵循TodoListViewControllerInput
协议,并添加实现所需的操作方法。extension ToDoListTableViewController: TodoListViewControllerInput { func displayAddTodoItemSuccess() { // 在该回调中处理添加待办事项成功后的操作 } // 添加更新和删除待办事项操作方法 }
-
在
ToDoListTableViewController.swift
文件中,实现用户输入操作时调用的方法,例如,添加待办事项或者导航到添加页面等。class ToDoListTableViewController: UITableViewController { @IBAction func addButtonClicked(_ sender: Any) { router?.navigateToAddTodoItem() } // 添加其他用户输入操作方法 }
-
在
TodoListRouter.swift
文件中,实现导航页面的具体逻辑。class TodoListRouter: TodoListRouterProtocol { weak var viewController: UIViewController? func navigateToAddTodoItem() { let addTodoItemVC = storyboard.instantiateViewController(withIdentifier: "AddTodoItemViewControllerID") as! AddTodoItemViewController addTodoItemVC.delegate = viewController as? AddTodoItemViewControllerDelegate viewController?.navigationController?.pushViewController(addTodoItemVC, animated: true) } // 添加其他导航 }
4. 完成其余的逻辑
-
在
AddTodoItemViewController
中,定义AddTodoItemViewControllerDelegate
和TodoItem
对象,并通过协议通知TodoListViewController
新的待办事项已经被添加。 -
在
AddTodoItemViewController
中,使用TodoListWorker
对象保存新的待办事项,然后通过协议通知TodoListInteractor
数据已经更新。 -
在
TodoListInteractor
中,使用TodoListPresenter
对象更新用户界面以显示新的待办事项。
在完成以上操作后,您可以使用 Clean Swift 架构编写的 To-do List 应用程序的 demo 就可以正常运行了!