Tag: 面向协议

协调员,面向协议的编程和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 4.1已有几天推出,并且具有一个有趣的功能: 条件一致性 。 这是用于实现面向协议的编程以及API设计的新工具。 这篇文章是对这种崭新技术的快速介绍,并且肯定会在接下来的几周内进行深入探讨。 和往常一样,您可以在我的个人博客上找到原始帖子。 借助Swift,您可能会对实现扩展的所有不同方式感到困惑。 随着语言的成熟,出现了新的扩展可能性,开发人员必须选择合适的语言。 基本上,扩展允许扩展类型的行为而不必将其子类化: 进行实用程序功能或实现有效的工厂模式很有用。 对专用于泛型类型的基本扩展进行了改进: 例如,将sum()函数应用于Bool数组可能没有意义。 这种扩展允许开发人员将新功能引入现有类型,但使它们可以安全地同时使用。 当您设计供其他开发人员使用的API时,这非常有用。 一旦满足良好要求,他们就可以一次“免费”地受益于某些代码。 扩展不仅可以将行为添加到现有类型,还可以修改类型本身以使其符合协议。 这在存在异质性的地方带来了一致性。 如果不使String , Ints和Optionals符合相同的协议,就不可能将它们混合在一起。 但是,尽管Array的每个元素都是“ Resettable ”,但我们仍然必须对其进行解析(使用map )并在每个元素上调用“ reset() ”以实现全局操作。 有条件的一致性将大大帮助希望重置整个Array的开发人员无缝地执行此操作。 到目前为止,我们还没有谈到面向协议的编程。 该范例具有向协议添加默认行为的能力。 符合此协议的类型也将有益于此默认行为(或覆盖它)。 这是一种特殊的扩展名,并不是本文的重点。 因此,在这里我们不要引入过多的噪音,而只关注扩展具体类型的能力。 条件一致性是Swift 4.1随附的全新功能。 它是条件扩展和一致性扩展之间的混合。 如此,它继承了它们的两个关键原则: 带来了新功能,但使它们可以安全同时使用 在存在异质性的地方带来一致性 实际上,其背后的主要思想之一是:如果可以将行为应用于超集的每个元素,那么我们可以考虑将该行为也应用于超集本身: 由于Array的每个元素都是Resettable ,因此整个Array也是。 例如,这正是苹果公司对Equatable和Hashable所做的事情。 使用Swift 4.1时,等于数组的元素数组是等于数组的。 在我们的示例中,最大的功能是,我们可以在根Array中嵌入一个Resettables数组,并且仅使用一条语句“ resettableArray.reset() ”,即可重置整个数据结构。 这是处理递归的一种非常优雅的方法。 如我们所见,就API设计而言,与基本的“ 一致性扩展 ”相比,使用“ 条件一致性 ”具有很大的优势。 API设计人员将在他的框架中内部化他认为很聪明的代码(此处为reset()函数),以免费提供给符合相应要求的开发人员。 […]

Swift中的JSON解析—第一部分:JSON解析的通用协议

对于iOS开发人员而言,解析JSON是一项非常常见的任务。 但是,Foundation框架提供的现成功能非常基础。 有许多可用的开源库可实现更高级别的功能,并有望使此任务更轻松,更安全。 作为个人实验,我尝试实现自己的JSON解析库,该库以我真正喜欢的几种方法为模型。 我的实现旨在实现极简主义,并专注于基于通用协议的方法,该方法应允许解析JSON内容,并以最少的代码将其存储在适当的容器( 类或结构实例)中。 为了使复杂性最小化,将没有特殊的错误处理:在不幸的情况下,解析特定的JSON密钥失败,相应的存储值将为nil 。 开箱即用的解决方案 假设我们需要与Web服务进行交互,该Web服务返回如下所示的JSON内容: { “位置”:[{ “ label”:“首页”, “数据”:{ “ address”:“ 6925 Felicity Coves”, “ city”:“ East Davin”, “ state”:“华盛顿”, “国家”:“美国”, “ zipCode”:“ 22998-1456” } }, { “ label”:“工作”, “数据”:{ “ address”:“ 0506 Gretchen River”, “ city”:“亨廷顿海滩”, “ state”:“ Connecticut”, “国家”:“美国”, “ zipCode”:“ 61182-9561” } }] } Swift通过NSJSONSerialization类提供了一种解析JSON的默认方法。 我们可以将JSONObjectWithData用于此类任务,并在确认返回类型符合我们的预期( […]

POP(面向协议的编程)-简介

在此处找到原始帖子。 前言 计算机是由多个硬件组件组成的复杂机器。 然后是一个软件层,可以有效地利用这些组件来执行所需的任务。 这些复杂的机器很多时候互相交谈以共享信息或委派一些任务。 所有这些任务在某个时间点都会处理数据。 对整个生态系统的研究被广泛称为计算机科学。 科学领域,其整个重点是使一组任务自动化。 我们将不断发展和改善现有的生态系统,并期望它能为我们做更多的事情。 在硬件组件上不时有值得称赞的改进。 随后,我们改进了软件方法,以充分利用这些笨拙的组件。 我们发明了操作系统,内核,编译器,并逐步对其进行改进以与硬件相匹配。 为了构建这些功能强大的软件,需要开发出具有更多功能和更多功能的新编程语言。 每种编程语言均出于一组目的而存在,并且支持一个或多个编程范例。 这样的范例之一就是面向对象的编程(OOP),它于1960年代初期引入,并从那时起被广泛使用。 这种范式要求我们根据对象来思考一切。 OOP通过其核心原理(抽象,封装,继承和多态性)具有解决现实问题的强大能力。 因此,许多编程语言已成为OOP的主要范例。 诸如C ++,JAVA,Objective-C等OOP语言通过分类,子分类,方法重载,抽象(协议)等支持了核心原理。 不过有一些注意事项– 所有这些功能仅可用于对象(引用类型)。 诸如结构和枚举之类的值类型无法利用这些功能,因此它们仅保留了数据存储空间而已。 我们失去了值类型是线程安全的巨大优势。 结果,我们不懈地致力于解决对象(引用)的线程安全问题。 同样,大多数OOP语言由于其性质的复杂性而不支持多重继承,因此不支持多重继承。 例如:假设歌手和演员都从其父艺术家Artist继承,他们都免费获得了Artist实现的通用功能 但是,如果要求说某些歌手也可能是演员,那么继承树将看起来像– 在这里,我们也将每个歌手都设置为演员 ,当歌手不是演员时,这会强制不相关的功能。 期望 这些惊人的OOP功能也应该有一种可用于值类型的方法,这样我们就不必担心解决线程安全的成本。 而且,如果我们可以在不给我们的类型带来太多复杂性的情况下带来多重继承,那么我们就可以完全避免上述问题。 解决方案—面向协议的方法 时间需要不同的思维方式。 超越OO方式的思考。 面向协议的方法。 但是首先,什么是协议? 协议是一组规则和要求(方法和属性),类型(值或引用)需要满足。 将协议视为其要求的抽象蓝图。 一个类型可以相应地实现这些要求,并称其符合协议。 此外,一种类型可以符合多种协议。 让我们尝试通过面向协议的方法来解决上述问题– 我们声明了三个协议, 艺术家 , 演员和歌手 。 演员和歌手都继承自Artist协议。 每个协议都已声明其要求。 例如,符合Artist协议的类型需要在其实现中定义名称和年龄。 同样,符合Singer协议的类型需要提供name , age , […]

Swift中面向协议的编程

通讯协定 Swift协议基本上是类/结构/枚举的契约,用于实现一组特定的方法和属性。 //协议示例 协议TableCellProtocol { func buttonTapped() } Swift会检查在编译时实现的类是否满足协议的要求。 因此,这使开发人员甚至可以在运行程序之前找出代码中是否存在任何问题或错误。 与类相比,协议还带来了更多的抽象。 什么是面向协议的编程? POP是一种新的编程方法,可以使用协议修饰我们的类,结构或枚举。 Swift不支持多重继承,因此,当您想向类中添加多种功能时,就会弹出问题。 POP使您可以使用支持多种实现的协议向类,结构或枚举添加功能。 OOP与POP 类之间的抽象建模依赖于继承。 子类将具有其超类的能力。 子类可以覆盖该功能,并添加特定的功能。 在您需要另一个班级的另一项技能之前,OOP可以完美发挥作用。 Swift中没有多重继承。 但是协议是蓝图,而不是父级。 协议通过描述实现类型应实现的内容来对抽象进行建模。 这是OOP和POP之间的主要区别。 OOP的另外两个优点是: 类型可以符合多个协议。 这带来了完美的灵活性。 协议也可以由类,结构和枚举扩展和采用。 在下面,我将创建一个武器协议,而不是类。 您可以为var和函数创建蓝图。 在协议中创建var可以使您的类通过强制定义该变量来使该协议符合该协议。 在此示例中,我们强制开发人员在使用Weapon协议时将名称,canFire和canCut vars添加到武器 协议武器{ var名称:字符串{get} var canFire:Bool {get} var canCut:布尔{get} } 现在,考虑一下我们有两种武器: 易燃,可切割。 我们将通过武器协议使用这些功能来创建所需的武器。 协议可燃{ var magazineSize:Int {get} }协议可剪切{ var重量:双倍{get} var steel:字符串{get} } 我们创建了技能和我们的武器协议。 让我们使用所有这些来创建结构。 […]

面向人文协议的编程

当心! Story ini menggunakan类似物Superhero dari DC Comics。 Sebagai程序员,Pasta sudah terbiasa dengan 面向对象编程 。 Dimana paradigma pemrograman itu banyak memberi solusi untuk membuat arsitektur 可重用 代码 。 Namun OOP sendiri juga memiliki beberapa kekurangan,Yang kemudian pada tahun 2015,Swift memperkenalkan 面向协议的编程 ,yang bisa menangani kekurangan tersebut。 Definisi 协议 sendiri adalah : 协议定义了适合特定任务或功能的方法,属性和其他要求的蓝图。 Setiap 方法,属性,dll,协议,类,类, 要求, 协议 。 […]

面向协议的编程

面向对象编程自80年代中期开始出现,我们大多数人每天都在使用它。 它使我们能够在程序中模拟现实世界的情况。 就像您有一家大公司的汽车管理应用程序一样。 一辆汽车将以“ 汽车”类别表示,您将为池中的每辆汽车创建对象。 通过抽象,您可以轻松地对更复杂的事物建模。 也许在典型的汽车旁边,您还有卡车或摩托车。 它们都具有马达,但并非都具有门或其他特征。 如您所见,这个概念使编程变得容易得多,这就是我们大多数人使用面向对象的编程语言的原因。 Swift也是面向对象的,但也有一些缺点。 面向对象设计的阴暗面 复杂 摩托车是双向的 , 双向的是机动车 , 机动车是可运输的 。 在大型应用程序中,继承树可以快速增长并变得非常复杂。 项目中的新程序员可能需要一些时间才能解决。 这是个大问题。 我们应该始终尝试降低复杂性并使其易于实现新功能。 并发 您可能希望使用线程来提高软件性能。 但是,处理数据时会遇到困难。 类在所有线程之间具有“共享状态”:类的数据位于堆内存中。 虽然每个线程都有自己的堆栈,但堆是共享的。 当多个线程尝试操纵对象的数据时,事情变得非常困难。 最后,您将创建一个互斥锁,这会导致性能高昂且容易出错(死锁)。 超类的实现 想象一下,您想实现一辆电动踏板车。 电动踏板车是MotorVehicle。 现在,MotorVehicle迫使您实现方法“ openDoors()”和“ closeAllDoors()” 。 实施MotorVehicle类的人没有想到某天某人想要实施电动踏板车的情况。 我已经看过很多次了,尤其是在大型复杂项目中。 您可能最终以空的正文和愚蠢的注释来实现这些方法。 这是不好的 Swift中没有抽象方法 在Java中,我可以使用抽象函数声明抽象类。 您不能创建抽象类的对象,但是每个实现都会继承该类中定义的非抽象方法。 Swift不支持此功能。 这就是为什么我最近在生产代码中遇到以下问题: 使用协议和值类型! 了解发生了什么:值类型与引用类型 创建类的对象时,程序将分配内存。 这项工作将由操作系统完成。 并且由于您以后可能想读取或修改数据,因此操作系统会告诉您内存中数据的存储位置。 这是您的数据位于内存中的“地址”。 该地址是一个十六进制数,例如“ 0xCAFEBABE” 。 以后,当您访问数据时,可以通过引用内存中的地址来访问数据。 […]

快速入门Swift中的面向协议的编程

首先,我不会理解为什么面向协议的编程要比继承等更好。 有很多有关该主题的材料,因此您可以发表自己的看法。 我只想与您分享一些我在学习过程中学到的好东西。 我目前正在将我的Objective-C库WANetworkRouting重写为Swift。 顺便说一句,我们在Wasappli的许多应用程序中都使用了该库,您应该尝试一下:通过一些配置行,您可以将应用程序连接到REST Web服务,并在几分钟内将数据缓存到CoreData。 我可能一直在说:我只是将我的代码翻译成Swift,但我想潜入该语言提供的新思维方式。 在过去的8年中,成为Objective-C开发人员使我的习惯变得异常激动。 在Swift中,我最喜欢的事情之一就是如何使用协议为类添加行为。 除了使用继承,您还可以摆脱任何层次结构并放宽行为堆栈。 您还可以精确地决定采用哪种行为,而不必在某个时候吃一堆意大利面。 这样做还鼓励您编写更可测试的代码👍 让我们深入研究代码:WANetworkRouting的功能之一就是能够执行GET myObject之类的功能,而无需知道API上的路由。 在OC库中,我有一个名为WANetworkRouter的组件(很明显),它注册WANetworkRoute,它具有一些属性,例如pathPattern (例如: pathPattern shelves/:itemID ), httpMethod ( POST , GET ,…)和对象类。 这主要是受RestKit和一种方便的配置方式(一劳永逸地配置所有库,以使内容分离)的启发。 例如,您可能正在编写此 然后,通过调用此方法,路由器将针对您的API构建路径。

在Swift中更轻松地使用JSON和POP编码

让我们从符合Codable的简单类型开始。 在这种情况下,我们将使用微博帖子,因为这是我现在花费太多精力的原因。 struct Post:可编码{ 让标题:字符串? 让内容:字符串 } 目前,我们大多数人都在像这样对JSON进行编码和解码。 let aPost = Post(title:nil, 内容:“一些非常有趣的评论”)//编码为JSON数据 让coder = JSONEncoder() 让数据=尝试? coder.encode(aPost)//从JSON Datalet解码器解码= JSONDecoder() 让restorePost =尝试吗? coder.decode(Post.self,来自:数据!) 这很好并且相对容易,但是每次仍然是相当数量的样板。 首先,您需要一个编码器/解码器,并且必须处理Codable API方法正在抛出方法的事实。 在此示例中,我try? 可选的返回方法。 如果您需要的不仅仅是返回值的可选值,那就更麻烦了。 然后,您将推出do-catch块以捕获和解析错误,如果您从不受控制的Web API消费JSON数据,则应该完全这样做。 借助一点点的POP,面向AKA协议的编程,魔术可以做得更好。 在可选返回值仍然足够的情况下。 将值类型存储到NSUserDefaults或以其他方式存储到磁盘以进行检索就是这种情况。 我们可以肯定地知道我们要存储和检索的内容,因此我们实际上并不需要错误捕获模式。 我们从我们的类型可以遵循的协议开始。 该协议没有任何要求,因为它将使用扩展程序来为这些便利功能提供默认功能。 协议JSONCodable {} 我们只希望此默认功能可用于已经符合Codable类型。 我们可以通过将协议作为Codable的扩展来实现这Codable ,但是我希望这些事情更加明确。 我们不想意外地忘记在其他Codable类型上使用这些方法,我们不确定可选返回是否足以满足要求。 为了实现这两个目标,我们将使用我们自己的显式协议JSONCodable并将其扩展JSONCodable也限制为Codable 。 这是我们的协议扩展。 它包含一些静态变量和2种方法,使其成为简单的代码行即可获取我们类型的JSON Data版本或从JSON Data中还原其实例。 扩展名JSONCodable其中Self:Codable { //我们方便使用的编码器和解码器。 //这些是类型要使用的静态变量 //本身而不是实例。 静态var编码器:JSONEncoder […]

使用协议扩展管理网络状态

内容? 载入中? 错误? 空吗 丢失… 今天早上,我打开了苹果的音乐应用程序,用一些歌曲抚慰了我的耳朵。 但是,当然,作为iOS开发人员,我更倾向于研究该应用程序的功能。 我发现的是应用程序处理状态更改的微妙方式。 因此,吸引我去寻找在应用程序中处理网络状态的最佳方法。 假设我们正在构建一个管理四个状态的应用程序,即: 1.内容:数据呈现给用户 2.加载:正在通过网络加载数据 3.错误:通过网络加载数据时遇到错误 4.空:无可用数据显示给用户 出现的问题是:我的代码可重用吗? 我是否遵循DRY原则? 如果我有不同的方法来管理不同类中的状态怎么办? 代码 重构容易吗? 如果您的回答是“否”,则可以参考“解决方案”,否则,请选择意大利面。 解决方案 在WWDC 2015上,Apple推出了面向协议的编程。 它具有最强大的功能: 协议扩展。 等一下你说什么 现在,到底是协议扩展 。 如果您不熟悉此概念,请参阅以下链接: https://www.raizlabs.com/dev/2015/06/protocol-extensions-swift-2-0/ http://machinethink.net/blog/mixins-and-traits-in-swift-2.0/ http://cutting.io/posts/stateful-mixins-in-swift/ 快速看一下演示 让我们从协议开始 我们有一个名为ViewStateProtocol的协议: 让我们来谈谈它。 我们有一个状态管理器类实例(管理添加和删除视图的类),加载,错误和空视图,错误消息和以States Type为参数的方法声明addView (包含各种状态的枚举) 现在,让我们对协议扩展进行一些魔术。 首先,我们创建了一个状态管理器类的实例,该实例负责添加和删除视图。 然后,我们创建加载,错误和空视图对象。 太棒了! 但是,我们仍然需要将这些视图添加到视图控制器的视图中。 那么,该怎么做呢? 没问题,我们有州管理人员来救援。 State Manager类将负责添加这些视图。 好极了! 我们做到了。 但是,等等,我们的State Manager类在哪里。 我们也来看看… 因此,我们拥有所有视图的默认实现。 但是我们如何实施呢? […]