Tag: mvvm

协调员,面向协议的编程和MVVM; Swift的防弹架构

MVVM或模型,视图,视图模型的起源来自于2005年发布此文章的两名Microsoft开发人员: 用于构建WPF应用程序的Model / View / ViewModel模式简介 它修复了标准MVC或模型View Controller范例中的一些叙述空白,特别是消除了产生View Controller的副作用: 1)比他们应该了解的多得多 2)成为应用程序逻辑的重点 3)比他们指定的任务更加负责 View Controller变成了庞大的文件,难以维护,不是模块化且难以重新利用。 因此进入视图模型。 太从作者的角度出发 该术语的意思是“视图的模型”,可以被认为是视图的抽象,但是它也提供了视图可以用于数据绑定的模型的特殊化。 在后一个角色中,ViewModel包含将模型类型转换为视图类型的数据转换器,并且包含视图可用于与模型交互的命令。 通过改变逻辑和数据并将其放置在VM中,您可以在整个应用程序中重用视图的数据。 好吧,以后再深入。 面向协议的程序设计 。 苹果公司(源)一直在积极推动这个概念,我可以写一篇有关该主题的文章,但是要取得的成果以及我们将如何使用它非常简单。 为了创建具有严格功能限制的高度可重用的View模型,我们将创建协议来告知我们如何创建模型。 一旦有了该模型,我们将创建存储所有信息的视图模型,并将其传递给我们的视图控制器。 协调员 。 据我所知, 协调员一词是Soroush Khanlou在2015年创造的。我看到他的作品有很多风味,而其他出色的开发人员对此主题的看法也是如此。 如果想要裸露骨头,请严格按照POP方法检查Niels Van Hoorn,但到目前为止,我最喜欢的是AleksandarVacić。 协调器完全解决了UI层中的数据流。 它们不保存也不包含任何类型的应用程序数据-他们的主要关注点是将数据从中间件改组到前端UI。 他们做什么: 创建VC的实例 显示或隐藏VC 配置VC(设置DI属性) 加: 接收来自VC的数据请求 将请求路由到中间件 将结果路由回VC 他对协调器进行了更进一步的更新,进一步巩固了它们作为视图控制器和模型通信者的演示者的地位。 如果您查看Navigation Coordinator则它是UINavigationController子类。 协调员应通过其创建和管理的活动来命名,并应为包含这些活动的UI的VC呈现并触发信息的创建。 今天,我们将创建一个简单的登录应用程序。 具有LoginViewController , SetupAccountViewController和ForgotPasswordViewController一个。 这些都是与用户的帐户信息和身份验证交互的叙述,并且从这些视图控制器馈入和处理的数据非常相似: 1)有些表格可以接受用户数据 2)然后需要验证和处理此数据 3)如果数据未经验证,则需要通知用户其信息不正​​确 […]

使用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应用程序中非常流行的模式),然后选择最适合您和您的目的的模式。 您还应该尝试试验现有方法并进行修改。 也许您会发现一些值得关注和使用的新东西。 或者,也许您会发现到目前为止尚不存在的,通用且可重复使用的东西,这不仅是您自己的完美选择,也是我们成千上万的软件设计师和软件工程师的最佳选择。 祝您好运并成功搜索!

MVVM和Clean Archi如何帮助使用BDD方法

我们将尝试演示MVVM和Clean Archi如何帮助以BDD方法进行开发(行为驱动开发)。 该示例源代码可在此GitHub存储库上找到。 本杰西/计算器 计算器–具有BDD,Clean Archi和RxSwift的示例github.com 好的方法是从用户需求和示例映射开始。 我们将使用一个非常简单的示例来描述一个附加项。 通过这个非常简单的示例,我们试图证明MVVM / Clean Archi / RxSwift概念不仅有助于使用BDD,它们也是有教益的。 使用这种严格的方法,我们必须思考:一些输入,一个转换函数和一些输出:有助于我们清楚地识别不同的步骤。 现在我们不再问自己:我可以在哪里使用测试以及必须测试哪些类…… 请享用 ! 😉

MVVM->避免“紧急汤”

设置 在过去的几年中与MVC和MVP在可可粉接触领域合作之后,我认为现在应该退后一步,考虑MVVM方法。 最近,我在Ben DiFrancesco上观看了一次演讲,他在会议上讨论了如何以及为何在项目中采用MVVM。 Ben解释了如何在您的ViewControllers中添加目标/动作,委派,通知,KVO和块(Swift中的闭包)实际上只是创建了这种“命令性汤”,在此情况下,您需要为业务逻辑和其他代码做出复杂的推理。 此外,由于您与特定于平台的框架紧密耦合,因此将代码测试和定位到其他平台变得更加困难。 从经验上来讲,当您想开始向应用程序添加扩展时,这绝对成为问题。 确保您的所有业务逻辑都适用于Today,Watch和其他扩展, 并且如果不小心处理实现,您的主应用程序将是一场噩梦。 回顾MVC 对于iOS中的MVC,控制器具有共同的职责; 表示逻辑与业务逻辑混合在一起。 这创造了Ben谈论的当务之急:“最终结果是使代码难以理解,难以测试并且[通常]丑陋的代码。” 让我们看一下MVVM如何尝试解决此问题。 MVVM概述 使用MVVM,我们引入了一个称为ViewModel的新对象,该对象封装了表示逻辑。 ViewModel使用一个模型或一组模型,并创建已预先格式化以在视图上呈现的属性。 Ben给出的示例是格式化字符串,确定子视图的颜色,设置显示/隐藏布尔值或确定表视图中的行数。 使用这种模式,ViewController的工作变得简单得多,因为它只是将ViewModel属性连接到视图属性。 示例应用 本着学习新事物的精神,我们将通过制作示例应用程序来测试MVVM技能。 想象一下,您刚刚被一家摄影公司聘用为新职位,他们委托您制作一个应用程序来展示公司的代理商目录及其投资组合。 他们决定使用Portfolious这个名字,是因为它在时髦/时髦的焦点小组中表现很好。 无论如何,在Portfolious中,您将拥有一个座席列表,其中包含与他们有关的数据以及他们的工作组合。 首先,您将使用此JSON占位符数据的子集和最近启用的最新网络库。 您可以在Github上签出完整的项目。 应用布局 使用Sketch,我们将创建一个视图来展示Portfolious的主题。 我们将有一个座席的表格视图,其中每个单元格将具有一些基本信息,例如其名称。 进入代理后,您将获得扩展的详细信息集(由用户模型提供)。 在此下方,我们将看到其相册的表格视图,其中每个相册将呈现该相册中照片的集合视图。 资料模型 对于我们的数据源,我们将使用三个主要模型:用户,相册和照片。 每个用户都是该目录中的一名员工,当您进入他们的个人资料时,我们会在其中添加他们最喜欢的照片的相册。 用户的定义如下: { “ id”:1 “ name”:“ Leanne Graham”, “用户名”:“布雷”, “电子邮件”:“ Sincere@april.biz”, “地址”: { “街道”:“库拉斯之光”, “ suite”:“ Apt。556”, “ city”:“ Gwenborough”, “邮政编码”:“ […]

Swift-MVC

MVVM , MVP和VIPER 几周以来,我一直在尝试了解有关iOS建筑模式的更多信息。 作为基本MVC的一部分,您可以找到有关MVVM,MVP和VIPER的一些不错的文章。 iOS架构模式 MVVM简介 使用VIPER架构iOS应用 我不确定他们。 而且我还是很困惑。 最后, Bohdan Orlov在他的文章中说:“ 没有灵丹妙药, 因此选择架构模式只是在您的特定情况下权衡取舍的问题 ”。 我也有类似的想法。 当您可以使用更好的MVC时,为什么将所有架构决策押注在某种时髦的流行模式上? MVC 我完全同意MVC被破坏的事实,因为View和Controller集成在同一文件中。 这是事实,使MVC成为谎言。 我还认为采用这种替代模式是因为Objective-C的功能不如Swift强大。 老实说,由于Swift,我们可以以其他方式使用MVC。 现在要容易得多。 扩展功能更加强大且显而易见。 结构和枚举现在是真实的模型结构。 易于理解和使用。 因此,如果使用MVVM , MVP和VIPER也很痛苦,为什么我们不简单地使用MVC ? 搜索图案 我想学习如何使用HealthKit Framework ,所以几天前开始了一个项目。 我正在使用该项目来发展和研究有关如何在Swift中使用MVC的想法。 距离完成还很遥远,但是我要坚持下去。 每天都在发展和更改代码。 Swift-MVC 线索之一是使用扩展来尽可能多地移出ViewController。 视图:UIViewControllerIt是View 。 所有View Life Circle都在那里,因此仅将View代码放入ViewController中。 控制器:扩展 将所有Delagate和Data Source代码添加到新的扩展文件中。 我们通常将View Controller内部拥有的所有逻辑扩展到一个新的扩展逻辑文件。 模型 结构和枚举。 将所有数据模式转换为新文件 通过这种结构,ViewController的长度为100行。 结论 […]

Swift中的MVVM

MVVM是MVC体系结构的增强版本,我们在其中正式连接视图和控制器,并将业务逻辑移出控制器并移入视图模型。 MVVM听起来可能很复杂,但它实际上是您已经熟悉的MVC体系结构的修饰版本。 一般来说,MVVM通常与功能性反应式编程结合使用,并且有很多FRP库,例如RxSwift和ReactiveCocoa。 但是,如果不熟悉FRP,仍然可以在项目中利用MVVM。 在本文中,我将演示如何在不使用FRP库的情况下采用MVVM。 模型视图控制器 让我们开始使用标准的MVC方法,该示例将在UITableView显示一个排序整数数组。 此外,我们可以通过单击右上角的添加按钮以正确的顺序插入新的整数,并通过滑动行来删除整数。 在这里,我只是创建一个名为DemoViewController的UITableViewController子类,并在其中实现必要的UITableViewDataSource方法。 另外,我还将插入逻辑放在addNewInteger方法中,将删除逻辑放在tableView(_ tableView:, commit editingStyle:, forRowAt indexPath:)方法中。 final class DemoViewController: UITableViewController { fileprivate var sortedIntegers = [1, 2, 3] override func viewDidLoad() { super.viewDidLoad() tableView.register(UITableViewCell.self, forCellReuseIdentifier: UITableViewCell.description()) let addButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewInteger)) navigationItem.rightBarButtonItem = addButtonItem } func addNewInteger() { let number = Int(arc4random_uniform(10)) […]

Swift4中使用MVVM的流程协调器[第1部分]

将所有逻辑嵌入ViewController会导致iOS应用程序开发中一个著名的问题,称为Massive View Controllers。 建筑师和开发人员开始采用新的体系结构来解决此问题。 所采用的一种这样的体系结构是MVVM(Model-View-ViewModel),它已在iOS应用程序开发中非常普遍(与RxSwift结合使用)。 MVVM使您可以取消应用业务逻辑的耦合,并可以测试用例和用户界面。 这导致可重用性和更好地维护代码库。 使用Segue在iOS中可以轻松实现视图控制器之间的导航。 它的易用性和可视化布局可见性将吸引您将所有导航逻辑都包含在视图控制器和情节提要中。 但是从长远来看,这将导致巨大的耦合和可重用性问题。 为了解决此问题,MVVM体系结构中采用的一种更清洁的方法是流程协调器。 协调器是基本的Swift对象,可以封装导航逻辑并使组件可重用。 本教程演示了将现有基于情节提要的代码重构为协调器导航流程的开始步骤。 在本集中,我们将从重构使用基本MVVM构建的现有代码库开始。 我们介绍了Flow协调器,用于将导航逻辑与Segue和ViewController分离开,并将其移至Coordinators。 我们定义了所有协调员都需要遵守的协议,并且协议定义引入了childCoordinators,这让父级协调员拥有一个引用,直到弹出或关闭它们为止。 如果您喜欢这些教程的质量,请喜欢,订阅和分享。 请观看以下链接提供的所有剧集: 第1集-https://youtu.be/fH9paWpCvQs 第2集-https://youtu.be/qLbUzwZrQjc 第3集-https://youtu.be/qLbUzwZrQjc 第4集-https://youtu.be/b1GadsUtB9s 第5集-https://youtu.be/EZtCOQyRK7w 第6集-https://youtu.be/T0yT6J_Mp9U 第7集-https://youtu.be/ur-U9nzazbc 第8集-https://youtu.be/6KC1GdLnez0 第9集-https://youtu.be/fT_VI1SiapQ 第10集-https://youtu.be/KvDd1JTCWC8 第11集-https://youtu.be/PnEOgW7Ccig 观看其他TOP编程教程,网址为: youtube.com/c/letscodeeasy 请关注我们: http://letscodeeasy.com www.facebook.com/letscodeeasy https://twitter.com/letscodeeasy

功能视图构建

在情节提要中还是在代码中创建视图? 作为iOS开发人员,我们非常清楚这个问题。 他们两个都有优点和缺点,但是最近我越来越喜欢用代码创建的视图。 什么是架构? 我曾经将MVVM与RxSwift一起使用,这基本上意味着控制器是通过结合Storyboard , ViewController和ViewModel来创建的。 如果我们删除Storyboard界面,则在哪里构建视图的正确位置? 让我介绍一下ViewBuilders。 考虑一下当我们构建一个称为HomeViewController控制器时的情况。 让我们创建一个名为HomeViewBuilder的帮助程序结构,该结构最终返回HomeView ,该抽象使我们能够访问组件(等效于插座)。 因此,我们最终得到以下架构: HomeViewBuilder的结构: 也许您已经猜到我们要通过管道化一些操作(例如添加/设置适当的组件)来构建此视图。 让我们定义一个简单的ViewBuilder协议: 我们还定义实现ViewBuilder HomeViewBuilder 。 当然,最重要的部分是buildView函数。 我故意向您展示了此方法的最终版本 。 这是唯一可以从外部访问的公共方法,这是一种梦想,我们现在要实现。 首先 ,让我们介绍流行的管道和函数组合运算符,这些运算符允许我们组合函数和对象: 管道运算符用于buildView函数中,其基本外观如下: 组成从类型Builder功能到Builder 将此转换应用于创建的构建器 好的,看起来不错,但是这些 install / setup 功能 如何 工作? 如果您对镜头了解不多,则一定要观看一些视频,了解这种模式的工作原理。 我在这里使用它们来编写单独的小段代码,并使它们可重用。 让我们考虑使用vertical轴创建UIStackView并将translatesAutoresizingMaskIntoConstraints标志设置为false 。 我们将在项目中使用多少个? 当然很多 我创建了一些项目全局的Style结构,该结构定义了常用的样式,这些样式是(View) -> View类型的转换函数。 这里有些例子: 因此,让我们构建使用其中一种样式的UIStackView 。 这是典型installer功能的实现: 多亏了镜头组成,它看起来很清晰,我们在应用程序中获得了很多可重用性。 但是,等等,我们错过了重要的约束设置…… 问题 通过使用锚,我们可以很容易地通过将一个锚连接到另一个锚来生成约束。 但是在这里,我们失去了像镜头所使用的流程那样通用和通用的功能。 解决方案:让我们定义另一个构建器。 我创建了一个名为FunctionalBuilders的库,该库包装了约束构建并使其使用起来更加美观。 […]

模型-视图-视图模型的建筑模式– Anil Sutariya –中

Model-View-ViewModel体系结构模式 iOS / Swift应用程序使用的Model-View-ViewModel(MVVM)体系结构模式。 MVVM是MVC的扩展,我们在其中正式将视图和控制器耦合在一起,但是将所有表示逻辑从控制器中移出到称为视图模型的新对象中。 在iOS / Swift上下文中,视图的角色由view + view控制器组合完成(参见图)。 在iOS上使用 Figure Model-View View-Model模式 这三个组成部分的作用总结如下: 模型:负责存储数据,与视图模型保持双向通信。 视图/视图控制器:表示模式的视图部分,并处理用户交互事件。 与视图模型保持双向通信。 视图模型:处理表示逻辑,与模型和视图/视图控制器保持双向通信。 处理与可能提供特定功能(如复杂的业务逻辑和网络请求)的其他控制器的通信。

在下一个项目之前,请学习MVVM

我不是iOS开发专家。 经过一个月的学习,我最近开始在Swift中为多个行业开发应用程序。 我确实喜欢每个初学者,并打开了Apple文档,并遵循了他们的指南。 苹果公司推荐的模式是MVC模式。 我按照大家都知道并珍惜的Model View Controller的经典原理开始构建自己的第一个应用程序。 从表面上看,iOS开发中的MVC模型与我们多年来使用的模型没有什么不同。 对我来说不幸的是,我一直对软件体系结构,简洁的代码和漂亮的软件感兴趣,因此将iOS和MVC结合使用非常麻烦。 几周后,随着视觉和幕后应用程序变得越来越复杂,问题就显而易见了。 在为iOS开发时,您的视图(也称为Storyboard)是一个简单的XML文件,其中包含所有不同的组件以及它们的坐标和约束。 这样做的结果是,与实例的实际功能相比,负责实例化和管理这些视图的ViewController文件变得混乱而庞大。 您开始在同一类中查看混合在一起的不同关注点:路由,模型处理,动画,视图填充…都在一起💀。 这种使用起来令人困惑和痛苦的方法,通常被称为Massive View Controller综合症。 于是去寻找其他选项,然后在此处输入MVVM 。 MVVM模式或模型视图ViewModel围绕应将模型处理和视图处理分开的想法而展开。 这样可以实现更好的可测试性,可读性并易于开发。 为此,我们将ViewController分为二。 View (仍然继承自Apple ViewController类)将填充视图并管理动画。 屏幕上显示的所有内容均受其控制。 ViewModel负责与API,数据库和其他信息源进行交互,并提取与其相应视图有关的信息。 实例化视图时, View将自身绑定到其ViewModel并将根据ViewModel提供的数据进行更新。 有多种方法可以实现这一点,但是Swift提供的我的首选方法是通过闭包。 为了说明这一点,让我们想象一个打印当前日期的愚蠢视图。 我们可以从设计ViewModel开始: 简单的ViewModel示例 这里, ViewModel公开了一个变量和一种方法。 fetchDate()方法将获取当前日期并为其分配一个私有变量。 每次设置此变量时,都会调用一个可选的公共方法updateDate 。 此方法是一个公共变量,可以通过View设置这样的方法: 简单检视 实例化ViewModel , View会将其闭包简单地附加到其ViewModel的公开变量,然后触发获取。 如果需要,setupView方法将使用初始内容填充视图。 当获取成功完成并且在fetchDateFromApi函数上updateDateClosure了回调时,将updateDateClosure并更新标签。 所有这些异步且易于维护。 唯一令我烦恼的是, View仍然必须通过prepareForSegue和其他方法来处理路由。 在实现表示和模型处理之间的清晰分离之后,我们不能简单地乐于在这种情况下进行路由。 为了解决这个问题,我创建了一个简单的路由器协议(与旧接口的Swift等效): 基本但清晰的路由器实现 viewController的init方法是一种便捷的init方法,无需查找相应的Storyboard 。 枚举和协议只是为了清楚起见。 但这使我们可以在文件中简单引用此路由器: 将路由器添加到先前的类中 […]