Swift中的VIPER设计模式,用于iOS应用程序开发。

设计模式是上帝给软件开发人员的礼物。 这些技术可最大程度地减少代码重复,防止高度耦合并标准化编写代码的通用方式,从而为开发软件时的重复出现情况提供了通用解决方案。 在这个故事中,我们将熟悉用于iOS开发的称为VIPER (视图,交互器,演示者,实体和路由器)的设计模式。

先决条件:在开始学习VIPER之前,请确保您了解建筑设计模式和委托模式。

什么是毒蛇?

毒蛇是一种实现“关注分离”范式的设计模式。 与MVP或MVC一样,它通常采用模块化方法。 一种功能,一种模块。 对于每个模块,VIPER具有五个(有时是四个)不同的类,具有不同的角色。 任何课程都不能超出其唯一目的。 这些课程如下。

查看:具有所有代码的类,用于向用户显示应用程序界面并获取他们的响应。 在收到响应后,View会提醒演示者。

演示者:模块的核心。 它从视图中获取用户响应并相应地工作。 仅用于与所有其他组件进行通信的类。 调用路由器进行线框图,交互器以获取数据(网络调用或本地数据调用),查看以更新UI。

交互器:具有应用程序的业务逻辑。 主要进行API调用以从源中获取数据。 负责进行数据调用,但不一定来自其自身。

路由器:进行电线成帧。 从演示者那里收听要演示的屏幕并执行该屏幕。

实体:包含交互器使用的普通模型类。

下面显示了VIPER的简单示意图

毒蛇的例子

我创建了一个简单的项目来解释毒蛇。 可以在GitHub上找到。 这是一个非常基本的应用程序,它显示了从外部API获取的新闻标题。 (:p没用)。

Viper是委托驱动的体系结构。 因此,不同层之间的大多数通信都是通过委派执行的。 一层通过协议调用另一层。 调用层从协议中调用函数。 侦听层符合该协议并实现该功能。

下面,我将解释如何在我的一个示例项目中实现VIPER。 我建议您在github中打开项目并阅读说明。

通讯协定

我为所有协议创建了一个单独的文件。

遵循命名约定来命名协议。 例如,“ viewToPresenterProtocol”。 因此,这是一个“协议”,将由“演示者”实施以收听“视图”必须说的内容。

  • PresenterToViewProtocol:演示者调用,View侦听。 演示者从该协议接收引用以访问View。 视图符合协议。
  • ViewToPresenterProtocol:查看呼叫,主持人收听。
  • InteractorToPresenterProtocol:Interactor调用,Presenter监听。
  • PresentorToInterectorProtocol:演示者调用,Interactor侦听。
  • PresenterToRouterProtocol:演示者呼叫,路由器监听。

应用流程

View具有对“ ViewToPresenterProtocol”的引用以访问“ Presenter”并符合“ PresenterToViewProtocol”。 在它的viewDidLoad()中,它调用协议的函数updateView()。

  //视图 
  var presenter:ViewToPresenterProtocol? 
 覆盖func viewDidLoad(){ 
super.viewDidLoad()
主持人?.updateView()
}

另一方面,Presenter符合“ ViewToPresenterProtocol”。 因此,它实现了updateView()函数。

  //主持人 
  var interector:PresentorToInterectorProtocol ?; 
  func updateView(){ 
interector?.fetchLiveNews()
}

在updateView()内部,演示者告诉交互者获取一些实时新闻数据。

Interactor符合’PresentorToInterectorProtocol’。 因此,它实现了fetchLiveNews()函数。 此功能尝试进行网络调用并获取数据。 它具有来自“ InterectorToPresenterProtocol”的引用以访问“ Presenter”。

  //交互器 
  var presenter:InterectorToPresenterProtocol? 

如果网络调用成功获取了数据,它将调用以下函数。

  //交互器 
  self.presenter?.liveNewsFetched(news:(arrayObject?[0])!) 

如果不

  //交互器 
  self.presenter?.liveNewsFetchedFailed() 

现在,演示者还符合“ InterectorToPresenterProtocol”。 因此,它实现了这些功能。

  //主持人 
  func liveNewsFetched(news:LiveNewsModel){ 
查看?.showNews(news:news);
}
  func liveNewsFetchedFailed(){ 
查看?.showError()
}

因此,它告诉视图是显示新闻还是显示错误。

现在,View符合’PresenterToViewProtocol’。 因此,它实现了showNews()和showError()。 在这两个函数中,view用获取的数据或错误填充视图。

实体层

上面在“应用程序流程”部分中,没有讨论实体层。 它不直接与应用程序流连接。 但这是交互器不可或缺的一部分。 实体层提供了一个模型,交互器可以使用该模型从获取的数据中创建对象。

路由器

路由器负责应用程序的布线。 在应用程序中更改屏幕是非常基本的事情。 在VIPER中,路由器层负责执行该操作。

前面我们已经讨论过,在VIPER体系结构中,每个功能都具有一个模块,并且一个模块包含这五个层。 演示者呼叫路由器以创建一个新模块。 然后,路由器首先启动所有层类并返回模块。

在我的示例项目中,应用内模块没有更改。 但是,路由会在应用程序首次启动时发生。 因此,在AppDelegate的’didFinishLaunchingWithOptions()’内部,将调用路由器的createModule()函数。 它返回一个模块。 然后,UIWindow类显示该模块的视图。

为什么和何时使用VIPER

VIPER遵循非常干净的架构。 它将每个模块彼此隔离。 因此,更改或修复错误非常容易,因为您只需要更新特定的模块即可。 VIPER还为采用模块化方法创造了一个很好的单元测试环境。 由于每个模块彼此独立,因此可以很好地保持低耦合。 因此,在共同开发人员之间划分工作非常简单。

当应用程序的需求非常符合要求时,应使用VIPER。 处理不断变化的需求可能会造成混乱和混乱的代码。 因此,不应将其用于小型项目,因为MVP或MVC就足够了。 另外,如果项目的所有开发人员都完全理解该模式,则应使用VIPER。

VIPER工具

如果要在项目中使用VIPER,最聪明的方法是使用自动模块结构生成器。 否则,为模块创建文件将是单调的。 网上几乎没有发电机。

  • Generamba
  • VIPER代码
  • 贵宾根

结论

就像任何其他设计模式一样,VIPER也是不言而喻的。 一个人需要动手才能理解整个图片。 我的建议是首先开始使用VIPER创建一个非常基本的应用程序,并在此过程中阅读在线资源。 我的github仓库也可能是一个很好的参考。

快乐编码🙂

神圣的孟加拉国万岁。

孟加拉国是一个隐喻的世界,高低戏曲,伟大的诗歌和音乐。 您与一个稻农交谈,然后找到了一位诗人。 您会认识清道夫,并且会找到一位出色的歌手。

让·休斯顿

参考

  1. https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
  2. https://medium.com/@ankoma22/the-good-the-bad-and-the-ugly-of-viper-architecture-for-ios-apps-7272001b5347
  3. https://github.com/MindorksOpenSource/iOS-Viper-Architecture/tree/master/iOS-Viper-Architecture
  4. https://sourcemaking.com/design_patterns