Tag: 设计模式

如何使用状态设计模式创建有状态的ViewController?

有状态的ViewController是什么? 然后,我们将有状态ViewController命名为具有许多状态的ViewController,该ViewController应该能够基于当前状态更改视图或组件。 创建一个有状态的ViewController可能很棘手,首先,对于某些屏幕,我们可以有不同的加载和错误视图,例如,在LoginViewController我们的UIButton内部有加载,并且错误消息应使用自定义警报处理。 我们的HomeViewController应该显示一个默认的加载视图和一个知道如何处理Error默认错误视图。 我们希望以不必在许多视图控制器中重复代码或行为的方式构建它。 我们可以使用状态设计模式来处理它。 状态模式为: 一种行为软件设计模式,允许对象在内部状态发生变化时更改其行为。 状态模式可以解释为策略模式,它能够通过调用模式接口中定义的方法来切换当前策略。 定义我们的状态 我们定义了.success , .loading和.error(error) ,我们认为创建协议并将其添加到我们的ViewController会很棒。 这种方法的问题在于,每个视图控制器都会有一个巨大的switch case并且可能会有很多重复的代码。 😒:-“是的!是的,但是您可以解决这个创建函数的问题。”您说。 😅:—好! 但这不能解决我们的问题,只能掩饰它。 另一个问题是:“如果添加另一个状态会怎样?”是的! 我们需要将其添加到每个switch case或创建default switch case 。 添加另一种情况将使我们修改使用Statable协议的每个类,从而打破开放封闭原则。 创建单状态协议 我们认为如果将enum和protocol更改为新protocol会更好: 现在好多了! 这消除了switch case问题,但并不是我们想要的。 现在,即使具有默认的加载视图或错误视图,每个视图控制器都需要具有这三种方法。 换句话说,我们仍然在重复代码。 诚然,这种改变并没有使任何事情变得更好。 😓 我通常会说: 如果您使用的协议方法具有默认实现,或者不会在每个类/结构中使用,则该方法不应存在。 破坏我们的状态协议 一些视图控制器不需要实现setLoadingState()或setErrorState(error: Error)这将由默认类处理。 因此,我们决定将协议分为三个部分。 这将是很棒的,因为我们可以创建默认的加载和错误视图: 默认加载视图 默认错误视图 并且还将自定义行为添加到某些UIViewControllers例如,如果您想更改在已定义的ViewController中的加载方式或自定义警报以显示错误消息,则可以在ViewController中处理所有三种协议,例如: 处理默认状态 最后,我们可以在ViewController中创建一个装饰器来处理所有状态,并在每次需要时在它们之间切换。 结论 使用这种方法,我们可以在需要时具有自定义的加载和错误视图,而在不需要自定义的时可以使用默认实现。 我们可以创建许多不同的类来处理加载,从而使我们的DefaultLoadingState关闭以进行修改,而打开以进行扩展。 我们将状态设计模式和装饰器模式混合在一起,以创建一个StatableViewController来处理视图控制器中的状态。 使用依赖注入,我们可以在单个入口点中从控制器更改加载和错误行为。 附:如果您喜欢此帖子,请在Twitter上分享,或在中等水平上推荐,或两者都=)。 这确实有助于我吸引更多人。 非常感谢。

Swift中的Erasure类型

使用Swift,您可以通过关联一个或多个通用类型来定义协议。 这些类型是使用associatedtype关键字定义的。 名称“ 通用类型 ”在这里有点被篡改,我们应该谈论预留类型的占位符。 确实,我们将这种协议视为通用协议时,并没有提供很大的使用灵活性。 如果您需要有关泛型类型的提醒,请参阅以下文章,概述其所有可能性。 随时访问我的博客以阅读原始文章(语法突出显示更好) 在本文的其余部分中,我们将依靠一个简单的案例: 杯子是一种可以容纳任何Liquid的类型。 显然,我们将使用协议来定义这两种类型。 液体是一种协议,它具有三种属性:颜色,粘度和温度(可变的) public protocol Liquid { var temperature: Float { get set } var viscosity: Float { get } var color: String { get } } 杯子是使用LiquidType关联类型声明的协议。 此关联类型必须遵守上述Liquid协议。 杯子展示了LiquidType类型的简单属性以及填充它的函数。 public protocol Cup { associatedtype LiquidType: Liquid var liquid: LiquidType? { get } func fill (with […]

[迅捷]干净迅捷(1)

MVC的所有其他应用程序。 –지개이크린을지VC지패턴으30–40 MVC패턴으로관리하기에가있습니다。 Model이유로模型。 视图。 控制器(MVC)由Massive View Controller提供给您…… controller다보면View controller가뚱뚱해지는것은정부다없습니。 清理Clean Swift포다하겠습니다。 清洁雨燕? 清理swift VIP로쉽게로VIP패턴을사용하게다。 https://clean-swift.com/접속해보면는이지에서문제문。다고같습니다같습니다。 ViewController的이수수정수리새로새운것을가하기하제 1 Model클래로로로Model Model만또한는는는는만만 토이하나의스토리보드를사용하는문제 재현하는데가생겨4시간을,그리고주일을가지지제 시를를하하하하하하를,,, TDD기법이제대로활용이안되는 现场场景5配景景物图景物图。 (ViewController,模型,交互器,演示者,路由器) 이제코드를보살펴다。 https://medium.com/swift2go/installing-the-clean-swift-template-in-xcode-6b4367006827방법이설명되어있습니다。 文件->新文件->文件清理Clean Swift场景场景이개의5개의이자동으로생성됩니다。 模型模型 型号–저장모든모델을저장。 Requset -API请求에보내지는데 响应-API로부터响应를拦截데이터를 ViewModel -UI관련된모든것을모든것을 工人迅捷 工作者-API / CoreData。 交互器데이터를다 Interactor.swift Interactor -Worker와Presneter照片。 VC-模型(请求)-交互者-工人-模型(响应)-交互者-演示者흐름이다。 演示者 Presenter -Interactor在ViewModel上进行下载。 용자에게사용자에게이터를보여질지결정한다 路由器.swift 路由器-사사이에서이데过渡과传递을리을다 이렇게설명해드렸습니다。 기본로설명을하여이잘이있습니이잘다실수도다。 https://github.com/Clean-Swift/CleanStore补充说明下载https://hackernoon.com/introducing-clean-swift-architecture-vip-770a639ad7bf。 […]

Swift 4中的桥接模式

桥接模式将抽象与其实现分离开来,以便两者可以独立变化。 当我第一次学到这个时,桥接模式使我非常高兴。 当您不知道确切的业务逻辑要实现时,但是由于项目的截止日期而需要丰富抽象时,它确实可以为您提供帮助。 当业务逻辑来自客户需求时,仅需对业务逻辑进行编码。 类型:结构图案 也称为:手柄/主体 结构体: 参加者: 抽象:定义抽象的接口。 维护对类型为Implementor的对象的引用。 RefinedAbstraction:扩展Abstraction定义的接口。 实现者:定义实现类的接口。 该接口不必与Abstraction的接口完全对应。 实际上,这两个接口可以完全不同。 通常,Implementor接口仅提供原语操作,而Abstraction基于这些原语定义更高级别的操作。 ConcreteImplementor:实现Implementor接口并定义其具体实现。 Swift 4实现: 让我们考虑客户的要求是绘制Circle和Rectangle,但是我们仍然不知道如何实现实际绘制这些图形的代码。 在实际情况下,可能由于缺乏几何知识或我们选择绘制哪个数字的第三方图书馆而发生。 那些不知道桥接模式的人将等到完成实际的图形实现后,这可能会延迟开发。 如果在这种情况下遵循Bridge Pattern ,则无需等待实现细节,只需创建我们的抽象类并在整个项目中使用该类即可。 一切都会清楚,让我们继续前进。 抽象基础类。 实施此基类,我们可以扩展抽象并制作将在项目其他部分中使用的具体类。 在下面的示例中, Shape是基础抽象类,而Circle和Rectangle是我们抽象的具体类。 注意draw()方法,实际上该图不是绘制而是与该类的其他类调用方法链接在一起的。 在这里, GraphicsAPI是称为“实现者”的类。 抽象类调用实现者类的方法,这是Bridge模式的关键部分。 在上面的代码中,编写了所有抽象类。 现在,需要根据业务逻辑/实现选择来实现实现者类。 桥接模式的用法精彩。 桥接模式适合于实现的运行时绑定。 根据我们的示例,您可能会注意到我们有2个具体的实现类。 您可以在运行时选择任何一个。 例如,您可以在运行时使用DirectXAPI / OpenGLAPI绘制“圆形”和“矩形”。 在此处找到完整的源代码:Github

在APIClient on上使用Decorator🎀和Builder🛠模式

几乎每个移动应用程序都需要Internet来执行诸如更新用户信息,检查新闻,保存游戏数据等操作。 因此,我们可以说这是我们应用程序的重要组成部分。 我通常使用Alamofire来完成这项工作,这是包装外部库的好习惯,因此我们可以随时更改它们,并相信这次会来。 包装可以通过创建协议来完成。 因此,让我们创建一个简单的APIClient ,它将接收parameters , headers和method来执行请求。 在下面,您可以看到此APIClient的示例 我们构建apiClient对象的方式可能会有些混乱,任何人都容易犯错误并忘记使用修饰符,例如忘记添加处理错误的行为。 因此,我们可以创建一个builder以帮助我们的开发人员确定将添加到apiClient对象的行为。 Builder是一种设计模式,旨在为面向对象的编程中的各种对象创建问题提供灵活的解决方案。 Builder设计模式的目的是将复杂对象的构造与其表示分开。 附:如果您喜欢此帖子,请在Twitter上分享,或在中等水平上推荐,或两者都=)。 这确实有助于我吸引更多人。 非常感谢。

使用MVVM设计模式构建新闻应用程序

在我最新的Udemy课程“ 使用Swift构建真实的iOS应用 ”中,我演示了如何实现与NewsAPI.org集成的完整News App。 这篇文章重点介绍了与使用MVVM设计模式实现iOS应用有关的一些重要概念。 设置NewsAPI帐户 在深入研究实现之前,请确保您具有NewsAPI帐户。 NewsAPI.org帐户将为您提供一个apiKey,它是对API进行成功请求所不可或缺的。 为了简单起见,我们将仅从API中获取并显示头条新闻。 顶部标题的链接如下所示: https://newsapi.org/v2/top-headlines? country =我们 &apiKey = yourapikey 这将导致以下JSON响应。 注意 :由于这是新闻,您的实际JSON响应可能有所不同。 但是结构保持不变。 Web服务和模型 设置NewsAPI帐户后,我们可以发出请求并将JSON填充到我们的模型中。 查看JSON响应,您会发现我们对articles数组内的项目感兴趣。 为了获得这些项目,我们必须对文章进行解码。 我们的Article类如下所示: 我真的希望您喜欢这篇文章! 如果您想了解有关使用MVVM设计模式创建iOS应用的更多信息,请查看以下我的课程: https://www.udemy.com/building-real-world-ios-apps-using-swift/?couponCode=MEDIUM [源代码] 谢谢,祝您编程愉快!

Swift 4中的命令模式

命令模式将请求封装为对象,从而使您可以将具有不同请求,队列或日志请求的客户端参数化,并支持不可撤销的操作。 当需求类似时,命令模式很有用–会有很多操作要做一个接一个的操作。 考虑到每个操作都非常耗时,因此您不能直接调用执行该操作的方法。 传入操作请求的速率高于整理每个操作。 要处理这种情况,您需要将每个操作/命令封装在一个对象(又称为命令对象)中,并将它们存储在队列中。 然后依次处理从队列中取出的每个命令。 这一切都与命令模式有关。 命令模式在日志记录框架,数据库事务和计划的操作中有多种用法。 Command模式的另一个不错的方面是Command Executor (可以是单独的线程)不需要知道命令以及与要执行的命令相关的上下文信息。 这样,可以随时构建更多的命令/操作,而无需更改已编写的现有代码。 类型:创作模式 也称为:动作,交易 结构体: Swift 4实现: 我们的上下文将是一个Book对象,我们要在其上执行不同类型的命令。 将有3种命令类型: Buy,Sell,GiftFriend 。 BuyCommand:从图书馆购买书籍,然后将所有者设置为我。 SellCommand:将书籍出售到图书馆,并将所有者设置为图书馆。 GiftFriend:将书赠给提到名字的朋友。 让我们编写上下文类Book。 您可能会对Book类中的buy(),sell(),giftFriend()之类的方法感到惊讶,并问自己这些方法应包含在命令类中。 没有! Command对象将调用这些方法,因为这些方法将执行实际任务。 如前所述,三种命令类: CommandExecutor负责一个接一个地运行命令。 它可能是一个不同的线程,但是为了简洁起见,在这里我们使用了while循环和runCommand()方法,它将一个接一个地运行所有命令,直到命令队列结束。 现在像往常一样,感受命令模式的力量。 您可以在此处找到完整的源代码:Github