Tag: 设计模式

使用Swift 3的IOS中的MVVM

当我们为最新的iOS应用程序奠定基础时,想向我们以前的iOS应用程序学习。 我们设定了两个目标: 避免Massive View Controller综合症 尽可能少的重复代码 iOS中的MVVM 自从最近出现更好的架构模式以来,MVC(模型视图控制器)设计模式就已经失去了其作为实际模式的地位。 现在,MVC被臭名昭著地称为Massive(或Messy)-View-Controller模式,其原因是在View控制器中堆积1000行以上的代码非常容易。 甚至苹果公司也以避开其示例代码中的MVC模式而闻名。 MVVM(模型-视图-视图模型)是一种体系结构模式,是MVC的替代方案,它可以使将ViewController的UI特定职责进一步隔离到视图模型变得更加容易。 在MVVM设计模式中, 模型与在MVC模式中相同,它表示简单数据。 视图由UIView或UIViewController对象以及它们的.storyboard和.storyboard文件表示,它们仅应显示准备好的数据。 ViewModel隐藏所有异步联网代码,用于可视表示的数据准备代码以及用于侦听Model更改的代码。 所有这些都隐藏在精心定义的API后面,该API建模为适合该特定View 。 使用MVVM的好处之一是测试,您可以在单元测试中更轻松地对其进行测试,而不会影响UI代码。 现在, 视图 ( UIViewController / UIView )变得更加简单,而ViewModel充当Model和View之间的粘合剂 。 在iOS Swift3中应用MVVM 如果您不熟悉MVVM,并且想深入了解如何在应用程序中实现和使用MVVM设计模式,请深入阅读本文,并附带示例示例。 我们将在此示例上演示iOS MVVM模式的用法。 简短地说,该应用程序显示一个用户列表,每个列表包含一个用户图像,其名称和电子邮件。 示例项目中使用的库: Alamofire:是一个用Swift(版本4.4)编写的HTTP网络库。 SDWebImage:该库提供了具有缓存支持的异步图像下载器。 Mapper:是一个简单的Swift库,用于将JSON转换为强类型对象。 步骤1:设定APIClient RANDOM USER GENERATOR使用的API,不需要密钥和授权令牌。端点是:http://api.randomuser.me/?results=10&nat=e 我编写了一个具有完成处理程序的downloadUser函数 。 JSON数据将以字典数组的形式返回,用于下面的关键“结果”。 步骤2:设置ViewModel。 #1:我创建了从NSObject继承的UserViewModel文件。 这将是我的View Controller中的属性,并由情节提要注入。 #2创建一个标记为@IBOutlet的apiClient属性,该属性将由情节提要实例化。 因为我知道情节提要将注入它,所以我可以使用(!)bang运算符,因为我知道它不会为零。 第3步:设置视图控制器。 用@IBOutlet声明UserViewModel属性,情节提要将实例化此ViewModel对象。 ViewDidAppear:在视图出现后调用-是使用userViewModel属性从API开始加载用户的好地方。 从API下载数据后,重新加载tableView以显示我们检索到的应用程序对象。 步骤4:如何使用情节提要定义Object属性。 从对象库中,将一个对象项目拖到视图控制器上,并将其插入VC的顶部。 […]

依赖注入-什么,为什么和如何?

我们将探索依赖注入,重点是快速的iOS开发,但是这个概念适用于大多数面向对象的语言。 我们还将看到在iOS环境中应用DI的一些实际注意事项。 本文是我深入实施DI并学习各种实践,理论方面的结果。 什么是依赖注入? “依赖注入”是5美分概念的25美元术语”。 是关于DI的经常重复的格言。 从本质上讲,DI意味着尽可能地通过从代码外部提供对象来代替在代码内部创建对象 。 因此,这个词。 构造函数,属性,方法通常是我们创建对象的地方,可以从外部替换。 因此,我们最终得到3种类型的注射。 构造函数注入 资产注入 方法注入 我们将在“如何..?”部分中探讨这三种类型。 为什么要进行依赖注入? 让我们在一个场景的帮助下进行讨论。 场景-Koala Koder! 假设您有一个具有用户登录名的应用程序。 用户模型struct / class封装了登录的用户数据。 假设您是Koala Koder(一个像树袋熊一样懒惰的程序员)。 您也许提出了一个既快速又肮脏的解决方案。 将用户模型存储在NSUserDefaults中,然后通过属性获取它。 众所周知,苹果是如何喜欢单例类的,所以我们遵循它们使UserModel成为单例。 问题,到处都是问题… 1.单元测试员Vader罢工! 一位高级开发人员突然转为阴暗面,开始抱怨单元测试 。 他/她将不允许未经单元测试的应用通过代码审查。 2.出现疯狂的新用例! 如果这还不够,则应该支持一个新的用例 。 我们的应用程序现在应该支持多个用户 。 3.“让我们移动到” 现在,我们还达到了用户默认设置无法扩展的地步,希望迁移到新的数据序列化方法。 现在,甚至UserProfile中的我们的获取器和设置器也不安全。 为什么会有问题? 因此,我们发现自己陷入了严重的麻烦。 让我们分析为什么。 1.单身人士很难测试 现在,如果要对使用此单例的viewcontroller进行单元测试。 在单元测试中,您将创建一个UserProfile对象,手动调用viewDidLoad或其他方法。 现在,您必须验证是否调用了UserModel.sharedInstance.greet() 。 由于UserModel.sharedInstance是不可变的,因此我们不能用扩展UserModel的模拟类替换它,该类将覆盖greetUser并设置一个可以检查的标志。 因此,我们的测试范围下降了。 2.代码约束内部的实例化会产生强烈的耦合,从而产生有害的约束 在我们的方案中,通过使用单例,我们将代码库绑定到单个UserModel,但是现在我们的应用程序需要多个用户模型。 因此,一般而言,使用单例将很难适应新的用例。 您以为单身汉的想法突然不再那么单身了 […]

斯威夫特的抽象工厂

抽象工厂模式提供了一种封装一组具有共同主题的单个工厂而无需指定其具体类的方法。 让我们来看一个例子,众所周知,轿车系列有不同的型号,例如紧凑型,中型和全尺寸。 SUV也具有相同的类别。 假设我们有两个工厂。 一种专注于紧凑型 ,另一种专注于全尺寸。 让我们开始实现这种情况。 这是不同尺寸的轿车和越野车。 它们都符合各自的抽象接口。 如您在下面看到的,我们创建了一个轿车抽象接口(协议),该接口被三种不同的类所采用。 谢谢 !!!

什么是VIPER?

VIPER是一种模式设计,代表了传统模式MVC(模型-视图-控制器)的替代产品,解决了控制器可以包含所有应用程序逻辑的问题,从而在组件之间产生了强大的耦合,并使难度更大。代码维护,例如使用MVC进行代码维护。 VIPER将应用程序逻辑的责任划分为多个组件,从而实现了更大程度的去耦以及更好的代码维护和测试。 这些组件将它们的名称命名为模式:(V)iew,(I)相互作用器,(P)ententer,(E)ntity和(R)outing或线框。 视图 VIPER中的视图是被动的。 他们向Presenter通知用户产生的事件,并期望他的响应与必须显示的数据。 视图负责了解如何显示数据和管理用户交互。 他们通过视图模型处理数据,其中包含必须显示的特定数据。 主持人 它们从视图中接收事件,并基于这些事件可以与交互器通信,以请求数据请求,或与路由或线框通信,以在应用程序中执行某些导航逻辑。 交互者回答后,演示者负责在业务模型(使用交互者)和视图模型(使用视图)之间执行转换数据。 转换后,它们将与视图通信,以通知要显示的视图模型。 演示者不知道如何构成视图。 互动者 他们负责执行所有业务逻辑。 他们使用业务模型或实体。 交互者必须处理来自演示者的请求数据。 因此,依次调用服务,数据库或在数据所在的任何地方搜索。 他们转换业务模型或实体中的数据。 处理完数据后,会将其提供给演示者。 交互者不了解用户界面。 实体 它们代表自己的应用程序业务逻辑数据,并由交互器处理。 路由 他们负责执行所有屏幕导航,进入应用程序。 路由也称为线框。 首先创建它们,它们自己负责创建其他组件:视图,演示者,交互者,并在它们之间建立关系。 它们接收主持人的请求,并负责在屏幕之间传输数据。 他们允许知道应用程序内导航的不同可能性是什么。 什么时候应该使用VIPER 当我们想要为我们的项目提供一个有序的结构,可以轻松,清晰地扩展并且可以重用时,您可以并行开发不同的组件而不会产生冲突。 VIPER促进了组件的测试,并且由于每个组件封装了不同的职责而可能产生的可能的bug。 何时不应该使用VIPER VIPER牵涉到许多组件的创建,如果您的项目很小并且您知道将来将无法扩展,那么这可能会带来不便。 另外,所有开发团队都必须完全了解VIPER,以避免与其他模式产生混合,这可能会妨碍项目的开发和维护。 例 我在这里留下一个在Swift中开发的小项目,作为具有VIPER模式的项目的示例。 希望对您有所帮助。 https://github.com/aortegas/VIPER_Example.git 请让我知道您对本文的看法,您的问题或产生的错误。 感谢您的反馈意见。 请享用! 阿尔贝托·奥尔特加(Alberto Ortega)

真实世界:iOS设计模式

Design Pattern是演讲,论坛甚至是15分钟的休息谈话中的常见主题。 您可以在书籍或互联网上找到很多关于它的东西,以及使用橡皮鸭🦆,咖啡店☕和比萨店🍕的许多示例。 当我开始学习时,我通常会理解这种模式,但是在考虑如何将其应用于我的代码时遇到了很多麻烦。 我知道Factory模式用于创建对象,但是为什么需要它呢? 我真的需要一个Factory来创建我的对象吗? 我写这篇文章的目的是带来一些我在项目中使用的设计模式的真实示例。 战略 策略模式可以在运行时选择算法。 代码不是直接实现单个算法,而是接收运行时指令,说明要使用的算法系列中的哪个。 我们可以基于运行时使用不同的算法,换句话说,我们不在乎实现是如何完成的。 算法需要一个知道如何fly的对象,一个Duck class也知道如何fly以及一个Rocket class 。 我们的算法不在乎我们的实现是否需要展开翅膀或一加仑的气体。 使用策略解决问题 在这个项目中,我们需要能够接收viewController但是我们还需要它具有一些预定义的行为,并且这是应用Strategy模式的理想场所。 移动应用程序中常见的ViewController是Login因此只需创建定义我们的LoginViewController操作和依赖项的协议即可。 我的意思是,我们可以将LoginViewController注入我们的项目中,我们不关心UI是否具有tableView ,任何animation或验证方法,但我们需要它知道如何执行login 。 您可以在此处阅读有关此特定问题的更多信息。 厂 工厂方法模式处理创建对象的问题,而不必指定将要创建的对象的确切类。 当您需要在运行时创建对象时,工厂模式很有用。 因此,如果用户想要芝士披萨,则如果他/她想要意大利辣香肠,则创建一个CheesePizza()创建PepperoniPizza() ftw。 使用工厂解决的问题 在使用strategy模式解决viewController注入问题的同一项目中,我们使用factory模式能够在运行时创建对象,并将其所需的所有依赖项传递给它们。 我们需要推送一个LoginViewController实例,可以使用诸如Storyboards , xib或view coded类的不同方法来创建该实例。 我们有一个工厂实例,可以通过更改工厂本身来创建对象的方式进行注入。 对于Factory的实例,我们只需要调用build方法。 这个工厂可以是我们并不在乎的ViewCodedLoginViewControllerFactory或StoryboardLoginViewControllerFactory的实例,我们只需要它来实现返回LoginViewController的build方法。 在这里,我们为每种对象都有一个工厂,但是我们可以有一个工厂,该工厂知道如何从storyboard xibs , xibs或viewcoded构建ViewController 。 装饰器 装饰器模式允许将行为静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为。 这是我最喜欢的模式,装饰器模式的经典示例是想在咖啡中添加鲜奶油并根据饮料计算新价格和描述的咖啡店。 使用装饰器解决问题 对于每个服务调用,我们需要不同的API版本,这可以通过许多不同的方式完成,但是我们使用此模式将自定义Header添加到Request 。 通过这种方法,如果将来一个API调用应在其标头中添加另一个参数,我们也可以做好准备。 我们还需要过滤请求中的结果。 可以通过创建新方法或更改请求的工作方式来完成。 我们决定使用Decorator来添加此行为,因为在其他类中使用了我们的服务,并且我们希望在先前的实现中更改最少的行数。 适配器 适配器模式是一种软件设计模式,它允许将现有类的接口用作另一个接口。 它通常用于使现有类与其他类一起使用而无需修改其源代码 […]

iOS-SOLID原则第1页-SRP

SOLID原则是5个OOP设计原则,可帮助您使软件更加灵活,可读性和可维护性。 在这个由五部分组成的系列文章中,我将介绍其中的每一个,并通过示例介绍其中的每一个如何为您提供帮助。 S —单一责任原则(或简称为SRP) 一个模块应该只有一个责任,只有一个改变的理由。 O —打开/关闭原理(OCP) 应该打开一个模块进行扩展,但关闭该模块进行修改。 L — Liskov替换原理(LSP) 程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。 I —接口隔离原理(ISP) 许多特定于客户端的接口比一个通用接口要好。 D-依赖倒置原则(DIP) 一个人应该“依靠抽象而不是凝结。” 在第一部分中,我将介绍第一个原理SRP。 我认为,这是iOS开发中最重要的5个。 “一个模块应该只有一个责任,只有一个改变的理由。” 从本质上讲,这意味着代码中的对象,类型,类或任何其他模块应负单一责任,这也是更改的唯一理由。 为了说明这一点,假设您有一个应用程序,用户可以在其中设置个人资料图片。 该图像仅显示给用户,因此可以将其存储在磁盘上。 没有SRP,用于编辑个人资料图片的视图控制器将如下所示: 它不在乎也不应该在意如何将食物带到餐桌上。 唯一的责任就是吃它。 他不需要知道您换了工作,升职或被解雇了。 他根本不在乎您如何工作,只要您将他需要的食物带给他即可。 —唯一要担心的是。 我们的下一步将是分离关注点。 就像上面的猫一样,我们的视图控制器不需要知道默认的配置文件资产名称,也不需要知道如何保存它或保存在哪里。 唯一的责任是在UIImageView上显示UIImage。 现在,我们需要一个将处理所有个人资料图片加载和保存的类。 我们可能最终会得到这样的结果: 因此,视图控制器现在看起来像这样: 如我们所见,将个人资料图片管理与视图控制器分离,可以为我们提供更高的可读性和灵活性。 首先,该类现在可以在其他视图控制器中使用,因为我们将个人资料图片管理职责分离到了另一个模块。 现在也阅读视图控制器会更好。 我们只需将图像从ProfilePicManager加载到将在完成时调用的闭包上,然后显示图像。 认为这种方法比第一种更好,但仍不是SRP。 因为如果我们需要保存的图像不是个人资料图片,还会存储更多图像吗? 在前面的示例中,我们将个人资料图片管理与视图控制器分开。 但是我们的ProfilePicManager没有单一职责。 目前它有两件事: 个人资料图片管理 从存储层获取数据(在这种情况下为文件系统) 从中获取图像或保存图像的方式不是ProfilePicManager的责任或责任。 唯一的工作是从存储层获取个人资料图片,并在用户选择图片时将其交给存储层。 一个模块应该只有一个责任,只有一个改变的理由 。 如果确实要仅更改存储层(例如,从文件系统存储更改为远程服务器存储),而这与ProfilePicManager无关,则也必须更改它。 那不是我们想要的。 在这种情况下,使用SRP,我们只想更改存储层模块。 为了实现这一点,我们将不得不再创建一个类来处理与存储层的通信-ImageStorage 。 […]

Swift中的功能设计模式:解释器

Swift与Java,C#和Objective-C不同。 这些都是出现在面向对象编程热潮高峰期的语言。 特别是Java和C#总是试图将您的解决方案压缩到面向对象的框架中。 自由功能不应该存在。 他们应该是某个班级的一部分。 从那时起,整个软件开发社区变得更加务实,并接受有时考虑功能而不是对象是有用的。 诸如Scala,Clojure,Swift,Kotlin和Julia之类的较新的编程语言都更加注重功能结构,而以OOP为代价。 最近,我读了Reza Shirazian关于Swift中的设计模式的博客,特别是解释器模式。 他展示了如何以Java和C#中的经典OOP传统实现设计模式。 我在这里想要做的是显示Swift中还有其他可用的方法。 这是功能性思维而非面向对象思维的演示。 这个想法是您尝试将问题组合成功能而不是对象的组合。 Reza的示例正在创建一个程序,该程序可以解析简单的数学表达式,例如: l + p-10.00 我们将不讨论如何从文本字符串创建解析树。 相反,我们将研究如何构建和评估表示该表达式的解析树。 因此,我们想要做的是创建一个抽象语法树,如上图所示,它表示我们的数学表达式。 Reza很好地介绍了这一点,因此我不再重复。 取而代之的是,我将研究如何在语法树中表示各个节点,以及如何将其组成以形成树以及如何评估该树。 下面是组成几个节点以形成这样的语法树的示例。 让expression =减去(add(variable(“ l”),variable(“ p”)),number(10.0)) 然后,我们可以使用绑定到变量l和p的值来评估它。 var结果= exp([“ l”:2.0,“ p”:4.0]) 在Reza的“面向对象”方法中,像“添加”节点这样的单个节点被表示为一个对象: 类添加:表达式{ var leftOperand:表达式 var rightOperand:表达式 init(leftOperand:Expression,rightOperand:Expression){ self.leftOperand = leftOperand self.rightOperand = rightOperand } func interpret(变量:[String:Expression])-> Double { 返回leftOperand.interpret(variables)+ rightOperand.interpret(variables) } } 他重复此模式来描述其他运算符,例如减法,除法和乘法。 […]

工厂设计模式

当在实现通用协议或共享通用基类的类之间进行选择时,将使用工厂方法模式。 这种模式允许实现子类提供专业化,而无需依赖它们的组件知道这些类的任何详细信息以及它们之间的关系 什么是工厂设计模式? 工厂方法模式选择一种实现类来满足调用组件的请求,而无需组件知道有关实现类或它们之间的相互关系的任何信息。 有什么好处? 这种模式巩固了决定选择哪个实现类的逻辑,并防止其在整个应用程序中扩散。 这也意味着调用组件仅依赖于顶层协议或基类,而不需要有关实现类或选择它们的过程的任何知识。 什么时候应该使用这种模式? 当您有几个实现通用协议或从同一基类派生的类时,请使用此模式。 什么时候应该避免这种模式? 在没有通用协议或共享基类的情况下,请勿使用此模式,因为此模式通过使调用组件仅依赖单一类型来起作用 让我们看一下示例: 协议JobContactProtocol { func sendRequestResumeEmail() } struct Contact { 变量名称:字符串 var job:工作 初始化(名称:字符串,工作:职位){ self.name =名称 self.job =工作 } 枚举Job { 案例IOS 案例Android } } IOSJob类:JobContactProtocol { var联系人:联系人 func sendRequestResumeEmail(){ 打印(“亲爱的\(contact.name)您是ios候选人”) } 初始化(联系人:联系人){ self.contact =联系人 } } AndroidJob类:JobContactProtocol { var联系人:联系人 func sendRequestResumeEmail(){ 打印(“亲爱的\(contact.name)您是Android的候选人”) } 初始化(联系人:联系人){ […]

MVVM和协调器模式一起

今天让我们来谈谈创建应用程序时的常见问题。 应该选择哪种设计模式? 实际上,在构建iOS应用程序时可以使用许多模式:MVC,MVP,MVVM,VIPER等。这些是iOS中最常用的模式,每种模式彼此之间使用不同的方法,但最后哪种方法最好? 这取决于您从事的工作,项目的规模以及构建应用程序所花费的时间。 如果您想了解有关这些模式的更多信息,可以阅读本文:Bohdan Orlov的iOS体系结构模式。 现在让我们讨论两种不同的模式: MVVM :视图模型负责以易于管理和显示对象的方式公开(转换)来自模型的数据对象。 换句话说,这是模型和view / viewController之间的桥梁。 这是避免Massive视图控制器将逻辑移至View模型的一种绝佳方法。 协调者 :协调者或中介者将负责我们的应用程序路由(导航),然后view / viewControllers不需要知道它们在哪里或是否在导航内,它们只需要将导航操作发送到协调员/调解员。 MVVM运行中 首先让我们看一下MVVM的工作原理,以及为什么这对我们非常重要。 这有点容易理解它是如何工作的: view / viewController将事件或任务发送到viewModel viewModel执行任务(在后端中获取内容,执行操作,获取模型等) viewModel通过以下方式通知viewController:KVO,委托,回调,绑定等。 实际上,如今,如果您听到“ MVVM”,则认为是Reactive编程,反之亦然。 尽管可以通过简单的绑定来构建MVVM,但是RxSwift和RxCocoa将允许您获取大部分MVVM。 这样,我们将使用RxSwift来获取一些数据,并使用RxCocoa将数据绑定到视图来制作示例。 首先我们有viewController: 在这里,我们有好处: 分发 —现在,我们的viewController不再关心模型,它只是将事件发送到视图模型,并执行任务,完成后将响应发送回视图控制器,实际上视图控制器不知道什么真正发生在后台,因为现在这不是它的责任:)。 可测试性 – 视图模型对视图一无所知,这使我们可以轻松对其进行测试。 View也可能已经过测试,但是由于它是UIKit依赖的,因此您可能希望跳过它。 可重用性 -由于我们的viewControllers不执行特定任务,因此很容易重用项目中的大量代码和视图以及视图模型。 可扩展性 —现在,由于角色定义明确并且视图控制器并没有像以前使用MVC(大型视图控制器)那样执行很多任务,因此项目易于更改或更新。 是时候到协调员了 我们的应用程序看起来非常好,但是仍然有一个大问题,如果我要转到另一个屏幕,该任务由谁负责,viewController,viewModel,该怎么办? 答案不是全部,我们需要架构中的新元素来处理应用程序路由。 让我们尝试将协调器添加到我们的应用程序中,但首先我们需要了解应用程序应在何处以及如何运行。 好的,它看起来比以前非常相似,但是现在我们有了一个新的组件协调器,它负责处理应用程序路由。 通常,您的项目中有许多协调员,因为您的应用程序中有不同的导航和模块。 您可以将协调器与UITabBarController,UISplitViewController等容器相关联,或与UINavigationController之类的导航相关联,这些是应用程序中最常用的容器和导航。 每次您需要创建其中一个时,就知道需要一个协调器来处理流程:)。 现在是时候编写一些代码并观看协调员的实际行动了。 首先,让我们更改视图控制器以了解用户何时选择行。 这很简单,我们只调用方法modelSelected(Repository.self) ,然后将存储库绑定到视图模型。 现在更新视图模型。 在这里,我们有一些新东西让我们看看: […]

使用Swift的iOS上的MVVM架构模式

MVVM ( 模型视图ViewModel )是用于在编程代码中分离各层的高级体系结构设计模式之一。 它是由Microsoft架构师Ken Cooper和Ted Peters发明的,用于简化UI中使用的事件驱动的编程,它是Microsoft WPF和Silverlight子系统的一部分。 除了MVVM模式外,还有另外2种是众所周知的,它们是MVC ( 模型视图控制器 )和MVP ( 模型视图演示器 )。 在本文中,我将仅描述MVVM。 我将在此处解释与此模式有关的所有必需的详细信息。 另外,我还将在这里以实际示例为例,说明为什么值得在您的iOS应用中使用它以及如何使用它。 愉快的阅读! MVVM将代码分为3个高级层 。 从最低层到最高层看,它们如下: 最低的Model层,负责处理应用程序的领域模型,这些模型可以直接传递到更高的ViewModel层。 除了域模型定义之外,该层还提供存储,更新,删除和获取高层使用的数据的服务。 中间的ViewModel层负责使用较低的Model层提供的数据处理应用的业务逻辑,并对来自较高View层的用户交互进行逻辑处理。 最高的View层负责根据ViewModel的业务逻辑呈现适当的应用程序UI,并在那里处理Model的数据,还负责用户的交互,以捕获并传递它们以供较低ViewModel层处理。 在iOS代码中,当每个较大的组件的基类是UIViewController和UIView时 ,这些类将充当View层。 在下面,您可以找到UML组件图,其中显示了具有相互依赖性的所有MVVM层。 答案很简单,将负责模型,业务逻辑和视图的3个基本层分开,这些基本层始终是每个iOS应用程序的一部分。 并且使它们彼此独立,不紧密耦合,而是相互补充。 使用MVVM模式准备它们使它们也可以在多个地方重用,并且可以独立测试,从而影响更好的代码稳定性和质量。 由于所有代码看起来干净,易读且令人愉悦,因此正好可以轻松地找到不需要集中所有不重要细节的内容。 对于软件架构师和软件工程师而言,最重要的是代码的组织合理,这就是我们所有人都应该追求的! 假设我们想实现一个非常简单的应用程序,使用户能够基于2个不同的搜索引擎来搜索人们的个人公共数据,假设它是Facebook和LinkedIn。 从UI角度来看,这些用户将能够选择上述引擎之一,以输入一些文本进行搜索,然后单击搜索按钮,然后将搜索结果返回给UI。 下面是一个示例性的iOS Swift代码原型,基于以上描述介绍了MVVM模式的用法。 模型组件 从以上所有描述中可以看到,但主要是在呈现的代码和UML图中,当您希望对iOS Swift代码进行分层时,MVVM体系结构设计模式似乎非常有用,尤其是在标题为“为什么要使用MVVM?”。 这就是为什么如果您关心此处提到的要求,并且希望您的代码满足这些要求,那么您绝对应该考虑在您的应用程序中使用这种方法。 我只想补充并强调,这不是实现这些目标的唯一方法,还有更多。 因此,我建议您熟悉其余的现有模式(至少是MVC,MVP,但也可以尝试VIPER作为iOS应用程序中非常流行的模式),然后选择最适合您和您的目的的模式。 您还应该尝试试验现有方法并进行修改。 也许您会发现一些值得关注和使用的新东西。 或者,也许您会发现到目前为止尚不存在的,通用且可重复使用的东西,这不仅是您自己的完美选择,也是我们成千上万的软件设计师和软件工程师的最佳选择。 祝您好运并成功搜索!