Shaula Blog

美丽的东西都是肤浅的

iOS - VIPER 架构

iOS 中的 VIPER 架构是 Clean Architecture 的具体实现之一,强调职责分离和模块化设计,特别适合中大型项目。VIPER 的名称由五个核心组件的首字母组成,各个组件的职责明确,协作流程清晰。

核心组件

View: 主要负责展示用户界面和接收用户输入。View 将用户事件传递给 Presenter,并根据 Presenter 的指示进行被动更新。此组件不涉及业务逻辑,而是专注于用户界面的呈现。

Interactor: 处理业务逻辑,包括数据的获取和存储等功能。该组件与 UI 无关,具有良好的复用性。它通过 Presenter 返回处理结果,并包含核心的业务规则,例如网络请求和数据库操作。

Presenter: 接收来自 View 的事件,并调用 Interactor 进行相应的处理。Presenter 负责格式化数据并更新 View,同时也处理导航请求并通知 Router。该组件充当 View 和 Interactor 之间的中介,不依赖于 UIKit。

Entity: 代表数据模型对象,通常是结构体或类。Entity 由 Interactor 使用,主要用于数据的传递,本身不包含任何行为逻辑。

Router: 负责管理模块之间的导航,例如页面跳转。Router 的任务是解耦模块之间的依赖关系,从而处理界面跳转逻辑并维护模块的入口。

数据流与协作流程

用户操作触发事件

  • View 捕获用户操作(如按钮点击),并通知 Presenter。

Presenter 协调业务逻辑

  • Presenter 调用 Interactor 的方法获取数据(如 fetchUserData())。

Interactor 执行业务逻辑

  • Interactor 完成数据操作(如网络请求),通过回调或协议将结果(Entity)返回给 Presenter。

Presenter 处理结果并更新 UI

  • Presenter 格式化数据(如转换为 ViewModel),驱动 View 更新。

导航处理

  • 如需跳转界面(如进入详情页),Presenter 通知 Router,由 Router 创建新模块并处理跳转逻辑。

模块化设计

  • 功能划分模块:每个功能模块(如登录、设置)独立包含 View、Presenter 等组件。

  • 依赖隔离:组件通过协议进行通信,减少耦合。例如,Presenter 通过 ViewProtocol 与 View 交互。

  • 示例结构

    LoginModule/
      ├── LoginView.swift          // 实现 View 协议
      ├── LoginPresenter.swift     // 处理逻辑,持有 Interactor 和 Router
      ├── LoginInteractor.swift    // 实现业务逻辑
      ├── LoginRouter.swift        // 处理跳转到其他模块
      └── Entities/               // 相关数据模型
    

示例代码片段

// View Protocol
protocol LoginViewProtocol: AnyObject {
    func showError(message: String)
    func updateUserInfo(_ user: UserEntity)
}

// Presenter
class LoginPresenter {
    weak var view: LoginViewProtocol?
    var interactor: LoginInteractorInput!
    var router: LoginRouterProtocol!
    
    func loginButtonTapped(username: String, password: String) {
        interactor.login(username: username, password: password)
    }
}

// Interactor
protocol LoginInteractorInput {
    func login(username: String, password: String)
}

class LoginInteractor: LoginInteractorInput {
    func login(username: String, password: String) {
        // 网络请求,成功后调用 Presenter
        presenter?.loginSucceeded(user: userEntity)
    }
}

优劣势与适用场景

  • 优势

    • 高可测试性:各组件职责单一,易于进行单元测试(如测试 Interactor 无需 UI)。
    • 代码清晰:避免了 Massive View Controller 的问题,逻辑分散到不同组件。
    • 可维护性:模块独立,修改或替换不影响其他部分。
  • 劣势

    • 代码量增加:在小型项目中,由于结构复杂可能显得冗余。
    • 学习成本:需要深入理解各组件的职责和通信机制。
    • Router 设计复杂性:需统一管理模块间的跳转,可能引入复杂依赖。
  • 适用场景:适合中大型项目、团队协作及长期维护需求高的应用。

对比其他架构

MVC: 在 MVC 中,ViewController 承担过多职责,容易臃肿,而 VIPER 则将职责分散,适用于复杂场景。
MVVM: 数据绑定简化了 UI 逻辑,ViewModel 代替 Presenter,而 VIPER 更强调模块化和导航解耦。

总结

VIPER 通过严格的分层提升代码质量,适合需要高可维护性和测试覆盖率的项目。尽管初期开发成本较高,但其清晰的架构在复杂场景中优势显著。开发者需根据项目规模权衡是否采用,并合理设计模块间的通信。