如果您是具有高级技能且经历过大量iOS项目的iOS开发人员,您一定会知道选择合适的设计模式非常重要。它可以帮助您的项目顺利运行,并使其更具可读性,灵活性和可重用性.
基于这些经验,在本Swift教程中,我们将讨论所有iOS设计模式,以便您高度概述iOS应用程序开发中可能和常见的内容。
- iOS设计模式简介
我正在建造房子,你必须有一个详细设计的计划。如果计划质量差,在建设时,工人将遇到困难。房子肯定不会很漂亮或安全。这也适用于任何iOS项目。事实上,成功运行的编程代码并不困难,但掌握MVC之外的漂亮架构工艺将为您的应用程序设置成功和可扩展性。
当客户端,产品经理或用户发生更改或更新时,将出现平庸体系结构的问题。如果没有可靠的初始设计,构建新功能会变得很难 如果没有使用好的架构模式,那么在不破坏当前代码库的情况下,您将很难进行任何进一步的修改。此外,当您的团队中的许多成员必须更改同一个大文件中的代码时,由于合并冲突,您会发现自己遇到了大麻烦。您的团队的工作效率会显着降低。
好的,不再谈论为什么我们应该探索我们可用的所有iOS设计模式。我们已经谈过它们了。今天,我们来看看四种最流行的iOS设计模式:
MVC:模型 - 视图 - 控制器
MVP:模型 - 视图 - 演示者
MVVM:模型 - 视图 - 视图模型
VIPERS:View-Interactor-Presenter-Entity(aka Model)-Router
2.模型和视图之间的关系
您可能想知道为什么视图模型总是出现在所有模式中。是啊,你说得对。对于每个应用程序,这两个部分起着重要作用:
- 图形用户界面(也称为视图):显示数据并接收用户的交互,例如轻击手势,长按,摇动等。
- 数据(也称为模型):存储为应用程序状态的实际用户信息(在服务器或iPhone上)。
在一个简单的应用程序中,我们可以将模型中的信息直接显示在屏幕上。对于UI的任何更改,我们会更新我们的模型,但并非全部。您的项目越大,应用程序逻辑就越复杂。我们必须验证,格式化,转换数据,甚至从服务器获取数据,然后在数据发生变化时立即更新视图。
在这方面,iOS设计模式的一般解决方案是通过将组件分成较小的组件来减少组件之间的相互依赖性,并且责任有限。在这篇Swift文章中,我们将弄清楚他们是如何解决这个问题的。我们将制作一个简单的应用程序并应用所有iOS体系结构模式(并向您解释,同时向您展示Swift代码示例),而不是引入一堆复杂和抽象的理论(您可以在Google上轻松搜索)它更容易理解。
注意:由于本文仅侧重于分析模式,因此我们不会详细介绍功能分析。
您可以在此处下载入门项目。
- MVC
现在让我们首先深入了解MVC。我们来看看下面的Swift代码:
var yourOrder: Order?
override func viewDidLoad() {
super.viewDidLoad()
dataInitialization()
updateUIBy(yourOrder)
}
@IBAction func didTapOnDecreaseButton(_ sender: Any) {...}
@IBAction func didTapOnIncreaseButton(_ sender: Any) {...}
@IBAction func didTapOnBuyButton(_ sender: Any) {...}
private func dataInitialization() {
yourOrder = Order(title: "", quantity: 0, price: 0.0)
}
private func updateUIBy(_ order: Order?) {...}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {...}
}
这看起来就像一个普通的视图控制器,对吗?我们的过程如下:
1。创建一个名为yourOrder的变量。这将是我们的模型。我们还有 dataInitialization函数初始化状态。
2.创建一个名为updateUIBy的函数 ,根据yourOrder的更改来更新UI 。因此,您可以看到Controller在模型更改时立即更新了UI
3.请注意以下功能:
didTapOnDecreaseButton
didTapOnIncreaseButton
tableView(_ tableView:UITableView,didSelectRowAt indexPath:IndexPath)
这些是用户与View交互的位置,在Controller收到新数据后,它将通过调用 updateUIBy函数更新视图层来更新数据模型。让我们看看其中一个是什么:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
yourOrder?.setTitle(templates[indexPath.row].title)
yourOrder?.setPrice(templates[indexPath.row].price)
updateUIBy(yourOrder)
}
现在让我们将下图中的架构与我们的项目进行比较
我们将: View < - > Storyboard文件, Controller < - > ViewController文件, Model:Regular文件。
如上所述,控制器将扮演管理角色,在模型和视图之间保持联系。根据模型的变化,它将决定视图需要显示的内容。如果需要,它甚至会改变视图。在此处下载完整的源代码以获取更多详细信息 您将更加了解我们在此处所描述的内容。让我们来看看这个应用程序吧。
它看起来很不错,但正如你所看到的,ViewController几乎可以做任何事情。在实际项目中,它还必须处理视图周围的其他逻辑,例如动画,显示/隐藏子视图,导航,传递数据,记录等,以及数据模型层的逻辑。这将使ViewController变得越来越大,这也是人们经常调用MVC Massive View Controller的原因。它最终跟随旧设计模式的错误脚步。让我们继续下一个模式,看看我们是否可以更好地设计iOS应用程序。
- MVP
好吧,让我们开始使用Model - View - Presenter设计模式。首先,我们创建一个名为OrderViewProtocol的协议 和一个名为OrderViewPresenter的类, 如下所示:
protocol OrderViewProtocol: class {
func updateModel(order: Order?)
func updateUI(order: Order?)
}
class OrderViewPresenter {
private var order: Order?
private weak var delegate: OrderViewProtocol?
init(order: Order?, delegate: OrderViewProtocol?) {
self.order = order
self.delegate = delegate
self.updateUIByOrder()
}
func setInformation(_ title: String, price: Double) {...}
func increaseQuantity(_ currentQuantity: String?) {...}
func decreaseQuantity(_ currentQuantity: String?) {...}
func updateUIByOrder() {
delegate?.updateModel(order: order)
delegate?.updateUI(order: order)
}
}
然后我们调整我们的ViewController,如下所示:
var yourOrder: Order?
var orderViewPresenter: OrderViewPresenter?
override func viewDidLoad() {
super.viewDidLoad()
dataInitialization()
orderViewPresenter = OrderViewPresenter(order: yourOrder, delegate: self)
}
@IBAction func didTapOnDecreaseButton(_ sender: Any) {
orderViewPresenter?.decreaseQuantity(quantityLabel.text)
}
@IBAction func didTapOnIncreaseButton(_ sender: Any) {
orderViewPresenter?.increaseQuantity(quantityLabel.text)
}
private func dataInitialization() {...}
private func updateUIBy(_ order: Order?) {...}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
orderViewPresenter?.setInformation(templates[indexPath.row].title, price: templates[indexPath.row].price)
}
}
在分析代码之前,我们需要知道Presenter的角色是什么。它将使用委托处理用户交互和UI更新等逻辑。当有任何变化时,它还负责更新模型。所以,我们的流程如下。这里有两个很大的不同点。你还记得MVC模式中的这三个函数吗?
* didTapOnDecreaseButton
* didTapOnIncreaseButton
* tableView(_ tableView:UITableView,didSelectRowAt indexPath:IndexPath)
是的,在MVC模式中,我们使用了一些代码行来更新我们的模型和UI。但是现在呢?只有一行代码。我们需要做的是将UI更改中的所有信息传递给演示者。演示者将完成剩下的工作。我们来看看这个
此模式中的ViewController被视为视图层的一部分。它只在UI上显示/显示数据。就这样。这显着减少了ViewController的工作量,并且只需要通过委托模式根据模型的最新更改来更新用户界面。
extension ViewController: OrderViewProtocol {
func updateModel(order: Order?) {
yourOrder = order
}
func updateUI(order: Order?) {
updateUIBy(order)
}
}
现在,请在此处下载完整的源代码并运行该应用程序。您将看到结果完全相同,但现在我们有更多的组件,具有更具体的职责,这是我们在编写iOS代码时需要牢记的最重要的设计原则。
5. MVVM
可以说MVVM模式是iOS开发者社区目前最受欢迎的架构之一。与MVP架构中的Presenter一样,ViewModel看起来像是连接View和Model的东西。但它仍然有一些关键的不同之处:
- ViewModel类可用于多个视图,因为它不需要了解有关视图的任何信息。
- ViewModel类通过绑定数据或Observer设计模式与View类进行通信。
由于这一点,当我们听到名称MVVM时,我们立即想到了反应式编程,反之亦然。它成为近年来发展非常强大的现代有效模式。请注意,如果您不在MVVM中使用绑定数据,只需将ViewModel用作处理数据或更新视图等类的类,它就会使ViewModel看起来像Presenter,它会将架构带回MVP。
6. VIPER
要谈论iOS VIPER模式,我们需要详细分析它,否则,它会感到非常模糊和混乱。因此,在本节中,我们将讨论VIPER的概述,并将在不久的将来写一篇关于此模式的单独文章。
在上面的模式中,这些中间层(例如Presenter或ViewModel)的负担也很大,当它需要处理动画或导航等视图的逻辑(特别是导航流和屏幕之间的数据传递)以及模型的逻辑。让我们看看VIPER如何使导航更有条理。
如您所见,在VIPER中,每个部分都执行一项特定任务。
- 观点:这里没有任何变化。该视图负责将用户操作发送到中间层并显示他们收到的任何内容。
- Interactor:这是这种模式中最重要的部分。这是解决业务逻辑的地方。
- 演示者:与演示者在MVP中的角色或ViewModel在MVVM中的角色一样,演示者将处理从用户的交互中接收的数据。它会将结果发送到视图层。它还要求路由器输入导航内容。
- 实体:实体就像往常一样。
- 路由器:VIPER部件将通过Router / Wireframe相互连接。它保留所有参考,并负责导航部分。
正如您所看到的,此模式为每个特定类细分了许多任务。通过将关注点分离到自己的组件中,我们实现了更具可扩展性的架构。另一个好处是 ,不同层之间的大多数通信都是通过委托进行的,因此它们非常独立,可以轻松替换和扩展。这种iOS设计模式大量利用Swift协议,这使其成为适合Swift编程语言的完美架构。
7.结论
最后,我们浏览了最流行的iOS设计模式。 它们对您的应用程序意味着很多,希望本文可以帮助您更好地理解它们。事实上,模式的选择取决于团队的能力或项目的复杂性。最后但并非最不重要的是,不要只是在一个类中放入一堆代码,因为它在那个时候更容易,即使它与它的责任相冲突。在写下代码之前一定要认真思考。
在完成之前,我们面临着挑战。在MVVM部分,我们没有示例代码,我们将为您提供这个有趣的部分。
请与您的社区分享这篇文章,以帮助我们传播世界。快乐的编码!