Tag: 设计模式

快速跳入设计模式

我们什么时候应该使用它? 当有一个以上的班级实例时会引起问题。 单例模式意味着在任何时间我们只能创建该类的一个实例/对象。 此模式阻止创建多个实例。 我们使用 Apple的 次数很多次 基础 API, 例如: UserDefaults .standard UIApplication .shared FileManager .default 示例:#1 这称为True Singleton或称为default 示例:#2 这与真正的 Singleton非常相似,我们将init声明为public ,从而允许创建其他实例 示例:#3 LocationService 我们应该注意些什么? 如果您只是试图将信息从一个视图控制器传递到另一个,则单例不适合 “单身人士有问题的最常见原因是测试” 在Swift中避免单身人士 单例要点: 单例模式将一类限制为仅一个实例。 注意过度使用此模式! 在创建单例之前,请考虑其他方法来解决该问题。

iOS的Menerapkan MVP

MVP merupakan sebuah设计模式yang merupakan singkatan dari模型视图演示者。 Selain MVP terdapat设计模式Yang Menurut Saya Cukup Bagus,Yaitu MVVM。 Mengapa kali ini saya membahas MVP? Alasannya Adalah karena saya sedang terlibat projek yang menerapkan MVP。 简单! 😀 阿帕杨膜MVP spesial?。 iOS用户界面UIViewController,UIViewController ini biasanya berisi barisan kode campuran antara kode UI,kode bisnis,dll sehingga membuat UIViewController berisi banyak sekali barisan kode。 MVP成员membuat pemisahan […]

在iOS应用中使用Coordinator模式的真实示例

当代的编程世界充满着潮流,谈论iOS应用程序是很重要的。 希望我没有误会说协调器是近年来最时髦的建筑模式之一。 因此,我们的团队在不久前意识到了尝试这种方法的不可抗拒的愿望。 特别是因为它获得了幸运的机会-逻辑上的重大变化和应用程序导航的全面重新开发。 该文章的第一版是用俄语编写的,并在此处发布。 问题 通常,视图控制器承担太多责任:它们直接“ UINavigationController命令”以拥有UINavigationController ,与同级视图控制器“通信”,甚至实例化它们并传递给导航堆栈,总的来说,它要做很多事情不在他们的责任范围内。 避免此类问题的一种方法是协调器。 事实证明,这还算是非常方便且非常灵活的:模式代码能够管理小模块(可能是唯一的屏幕)和整个应用程序(相对而言,直接从其开始)的导航事件。 UIApplicationDelegate )。 历史 Martin Fowler在他的《企业应用程序体系结构模式》一书中将这种模式称为应用程序控制器。 Soroush Khanlou被认为是iOS环境中的第一个推广者:它始于2015年他在NSSpain会议上的演讲。然后,他的网站上出现了一个思想片段,该思想片段具有多个扩展名(例如,这个扩展名)。 然后是许多概述(“ ios协调器”查询提供了许多质量和细节各异的结果),包括有关Ray Wenderlich的教程和Paul Hudson的“用Swift入侵”的文章(在有关“大规模”视图问题的系列出版物中)控制器)。 向前运行,最引人注意的讨论主题是UINavigationController “后退”按钮的问题。 因为点击它不会被我们的代码处理,所以我们只能有一个回调。 为什么有问题? 像任何其他对象一样,存在于内存中的协调器必须由另一个对象拥有。 通常,当通过协调器构建导航系统时,其中一些会创建其他并在其上存储强大的参考。 子项完成后,父项将控制权收回,子项协调器使用的内存必须释放。 Khanlou对问题的解决方案有自己的见解,并注意到其他一些推荐的方法。 无论如何,我们会回到原点。 第一种方法 在显示任何代码之前,我想解释一下,与真实的设计原则完全一致的代码片段和使用示例在不会妨碍良好感知的地方会得到简化和缩短。 当我们第一次开始尝试模式时,我们没有足够的时间和自由度:我们必须考虑现有的设计原则和公认的导航系统。 第一个版本基于拥有并控制UINavigationController的通用“路由器”。 它可以对UIViewController实例执行与导航有关的任何操作:“按下” /“弹出”,“显示” /“关闭”,以及使用“根视图控制器”的操作。 接口示例: 导入UIKit 协议路由器{ func present(_模块:UIViewController,动画:Bool) func dismissModule(动画:Bool,完成:(()-> Void)?) func push(_模块:UIViewController, 动画:布尔, 完成:(()-> Void)?) func popModule(动画:布尔) func setAsRoot(_模块:UIViewController) […]

单例,立面和命令模式

外立面设计模式,单例设计模式,命令设计模式,Swift,Objective C,iOS 本周,我们将学习三种新模式,单例,立面和命令。 Singleton :Singleton Pattern确保一个类只有一个实例,并提供对其的全局访问点。 外观 :外观模式可让您计划对子系统的更改。 命令 :将请求封装在对象中,允许将具有不同请求的客户端参数化,允许将请求保存在队列中。 单例模式是一种软件设计模式,它将类的实例化限制为一个对象。 当仅需要一个对象来协调整个系统中的动作时,这将很有用。 在目标C中: 在Swift中: 抽象工厂,构建器和原型模式可以在实现中使用单例。 外观对象通常是单例,因为只需要一个外观对象。 状态对象通常是单例。 单例通常优于全局变量,因为: 1.它们不会用不必要的变量污染全局名称空间(或在具有名称空间的语言中,它们包含的名称空间)。[4] 2.它们允许延迟分配和初始化,而许多语言中的全局变量将始终消耗资源。 外观是充当前端接口的对象,可掩盖更复杂的基础代码或结构代码。 iOS iOS中的一个示例是UIImage类,该类是一个外观,它提供了一个用于使用和加载基于矢量或基于位图的图像的接口,因此,无论应用程序使用哪种图像类型,它可以使用UIImage并且不知道该类下发生了什么。 在目标C中: 在Swift中: 命令模式是一种行为设计模式,其中的对象用于封装以后执行动作或触发事件所需的所有信息。 Command设计模式可以解决哪些问题? 应该避免将请求的调用者耦合到特定的请求。 也就是说,应该避免硬性要求。 应该可以用请求配置一个对象(调用一个请求)。 将请求直接实现(硬连接)到类中是不灵活的,因为它在编译时将类耦合到特定的请求,这使得无法在运行时指定请求。 命令设计模式描述了什么解决方案? 定义用于封装请求的单独(命令)对象。 类将请求委托给命令对象,而不是直接实现特定的请求。 这样一来,便可以使用用于执行请求的命令对象来配置类。 该类不再与特定请求关联,并且不知道(独立于)如何执行请求。 在Swift中:让我们为命令和切换功能创建一个协议。 假设有两个设备支持例如ex的打开/关闭功能:空调,空气净化器。 我们有一个接口,它定义了接收者可以执行的操作 -Switchable 。 由于每种设备都有两种类型的命令,因此我们需要为每种设备实现具体的命令,如下所示: 打开/关闭设备的命令 -ConcreteCommand 测试班或客户 通过实现命令模式,Controller类不知道设备类型及其实现,但提供用于处理设备的接口。 下一页:装饰器,介体和桥模式 希望您喜欢,请随时发表评论或鼓掌鼓励🙂 参考文献: https://zh.wikipedia.org/wiki/Singleton_pattern https://zh.wikipedia.org/wiki/Facade_pattern https://zh.wikipedia.org/wiki/Command_pattern

Swift解决方案:网桥

我想请您注意抽象汉堡包及其作为餐食的具体实现。 假设我们要添加一个新汉堡,您需要创建多少个其他类? 如果回答三个,那将是正确的: 两个层次 这是不直观的,但是避免这种混乱的解决方案是创建两个单独的层次结构。 这是定义在声明时的含义: 桥接模式将抽象与其实现分离开来…… “抽象”是指基类或协议。 在我们的示例中,它涉及各种汉堡类。 这些汉堡包不会被实例化,因为餐厅不会单独出售它们。 必须使用实现将它们分类为一顿完整的饭菜才能使用。 “实施”是指我们在将汉堡包加入餐边后制作的餐食类。 因此,我们将汉堡包(抽象)与餐食/面食(实现)分离,并剩下两个类层次结构。 层次结构之间的桥梁 然后定义继续说: 桥接模式将抽象与其实现分离, 以便两者可以独立变化。 现在我们有了两个单独的层次结构,我们需要一种连接两者的方法。 为此,我们为每个Burger赋予Side类型的属性。 这种“具有”关系是连接两个层次结构的“桥梁”。 我们这样做是为了使两者可以独立变化。 换句话说,我们不再需要为汉堡和面包的每个组合创建一个类。 由于它们的层次结构是分开的,因此每个新汉堡或一面只需要一个新类。 这一切似乎有点抽象,所以让我们回到代码中进行演示。 编码解决方案 我们需要针对设备和音频类型的单独层次结构。 让我们从音频类型开始: protocol AudioHandling { func handle(audio: Audio) -> Audio } class AudioEncryptor: AudioHandling { func handle(audio: Audio) -> Audio { // Encrypt and return Audio } } class PlainAudioHandler: […]

iOS和Swift Universe中的访客设计模式

(本文最初是用俄语撰写的,并在此处发布。) 访客是由四人帮(GoF)在其经典著作“设计模式:可重用的面向对象软件的元素”中描述的行为设计模式之一。 简而言之,当需要对一组不同类型的对象执行一些类似的操作时,此模式可能很有用。 或根据对象的特定类型执行操作,而不知道该类型。 换句话说,模式可以通过添加相似或具有相同来源的操作来扩展一组类型的功能。 而且,类型结构和实现不会改变。 当然,最简单的解释方法是通过示例说明其用法。 无论如何,我想修正一个事实,即所提供的所有示例和代码段并非取自我的工作经验,而是出于学术目的。 即,本文试图使您熟悉一种 面向对象的技术, 而不是讨论要解决的特殊问题。 我想说的第二件事是,这里的所有代码都是为了更好地理解而结构化的,并且可能存在各种甚至明显的缺陷。 例 假设我们有一个UITableViewController ,它使用了几个UITableViewCell子类: ClassCell类:UITableViewCell {/ ** /} SecondCell类:UITableViewCell {/ ** /} class ThirdCell:UITableViewCell {/ ** /} TableVC类:UITableViewController { 覆盖func viewDidLoad(){ super.viewDidLoad() tableView.register(FirstCell.self, forCellReuseIdentifier:“ FirstCell”) tableView.register(SecondCell.self, forCellReuseIdentifier:“ SecondCell”) tableView.register(ThirdCell.self, forCellReuseIdentifier:“ ThirdCell”) } 覆盖func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell { / ** /返回FirstCell() / ** /返回SecondCell() […]

iOS中的Model-View-ViewModel模式

MVVM设计模式的组成部分 要了解ios中的mvvm,我们将举一个简单的示例,从url下载用户数据并将其显示在UI上。 用于示例应用程序的网址:https://jsonplaceholder.typicode.com/todos 响应: [ { “ userId”:1 “ id”:1 “ title”:“ delectus aut autem”, “已完成”:false }, { “ userId”:1 “ id”:2 “ title”:“ quis ut nam facilis et officia qui”, “已完成”:false }, { “ userId”:1 “ id”:3, “ title”:“ fugiat veniam minus”, “已完成”:false } MVVM架构 模型 :模型对象封装了特定于应用程序的数据,并定义了处理和处理该数据的逻辑和计算。模型对象可能与其他模型具有一对一或一对多的关系。 ViewModel :ViewModel处理驱动视图的业务逻辑,它拥有如上图所示的数据模型,由View / viewcontroller拥有,并提供要在UI上显示的输出。 View / ViewController […]

与Objective-C Swift代码兼容

(本文最初是用俄语撰写的,并在此处发布。) 尽管Apple已向我们提供了有关如何在Objective-C应用程序中使用Swift代码的详细文档(反之亦然),但在此方面还远远不够。 当我需要为Swift框架提供与Objective-C的兼容性时,Apple文档提出了更多问题,然后给出了答案(或者至少留有很多空白)。 密集的搜索证明该主题的照明效果很差:有关StackOverflow的几个问题和一些介绍性文章–这就是我所发现的全部。 本出版物是对找到的信息和我自己的经验的概括。 所描述的所有方法并不能声称是一个很好的实践,它们只是提供了一种解决问题的方法。 TL; DR。 为了在Objective-C中使用Swift代码,必须牺牲一些Swift功能,并为原始的Swift代码编写一个包装程序,该代码将不使用不兼容的功能(例如结构,泛型,枚举关联值,协议扩展等)。 所有包装器类都必须继承NSObject。 开始 因此,我们有一个基于Objective-C的项目以及一些想要在其中使用的Swift代码模块。 例如,它可以是在CocoaPods的帮助下添加的Swift框架。 像往常一样,我们向Podfile添加依赖项,运行pod install ,打开xcworkspace文件。 要使Swift框架可见,就不需要使用整个模块(就像我们在Swift中所做的那样)或单个文件(就像我们在Objective-C中所做的那样)导入。 必须导入的是一个名为-Swift.h的文件-这是自动生成的头文件,该文件是Objective-C代码与Swift公共API之间的连接链接。 看起来像这样: #import“ YourProjectName-Swift.h” 在Objective-C中使用Swift类 如果您可以立即使用Objective-C中的某些Swift类或方法,那么您很幸运:有人为您解决了兼容性问题。 事实是,Objective-C仅消化NSObject继承者和属性的公共API,初始化程序和方法必须由@objc属性标记。 处理自己的代码时,您始终可以继承所需的任何内容并添加任何属性。 当然,在这种情况下,您甚至可以用Objective-C编写,对吗? 因此,最好专注于他人的代码。 我们可以做什么? 写包装纸。 例如,考虑以下Swift类: 公共类SwiftClass { 公共功能swiftMethod(){ //此处执行。 } } 我们创建自己的Swift文件,导入外部Swift模块,创建NSObject继承类,并在该类内部创建想要的Swift类型的私有属性。 最主要的是一个通过属性调用原始Swift类型方法的方法: 进口基金会 导入SwiftFramework 公共类SwiftClassObjCWrapper:NSObject { 私人让swiftClass = SwiftClass() @objc 公共功能swiftMethod(){ swiftClass.swiftMethod() } } ( NSObject和@objc属性都可以从Foundation获得。) 显然,我们不能使用相同的名称。 但是我们可以使用原始名称将包装器API公开给Objective-C: @objc(SwiftClass) […]

MVVM-2:深度学习

在这里,我们又回到了MVVM系列的第二部分。 如果您不熟悉MVVM,则希望阅读本系列的第一个博客MVVM — 1:一般讨论,以使MVVM更加清晰。 为什么只留下一个简单的MVVM演示? 如所承诺的那样,这将是在MVVM公园中进行的详细游览,因此是一个大博客;)。 所以等我直到最后。 你会学到什么? 在实时iOS应用程序开发场景中使用MVVM。 建立复杂的UI尊重MVVM概念。 MVVM中遇到的常见问题并巧妙地解决了这些问题。 激动…… MVVM的缺点: 在探讨主要概念之前,让我们回顾一下MVVM的常见缺点: 难以在嵌套视图和复杂UI中管理视图模型及其状态。 各种MVVM组件和数据绑定之间的通信可能很痛苦。 视图和视图模型的代码可重用性很困难。 初学者的MVVM很难使用。 我们要建造什么? 我们将构建一个应用程序,该应用程序将获取您的当前位置并显示附近的自动取款机,咖啡馆,夜总会和您周围的餐馆之类的地方,因此,如果您想出去玩,这对您来说真的很容易:)。 没有比NEARBY更好的名字了。 该应用程序的外观如下: MVVM的基本经验法则: 视图模型归视图所有 , 模型归视图模型所有 。 View Model仅负责处理输入到输出以及驱动UI所需的逻辑。 视图模型不应修改UI。 该视图应仅负责UI处理。 视图不应与数据模型交互,反之亦然。 在构建我们的应用程序时,我们将尝试维护MVVM的这些基本规则。 因此,不浪费时间,让我们进入竞技场。 样例代码: 您可以下载示例代码,并在MVVM-2文件夹下打开“ Nearby”项目。 代码流: 该项目包含三个页面:主页,位置列表和位置详细信息页面。 为了便于理解,每个页面都被视为一个单独的模块。 对于此讨论,我们将分析HomePage模块。 其他模块的设计类似。 主页模块 通过分析HomePage设计,我们可以将页面中的视图分离为主页视图,分页单元格和带有集合视图的表格单元格。 此外,分页单元格具有水平滚动视图,该滚动视图具有显示位置细节的视图。 如果您考虑如何管理所有视图模型并在组件之间划分职责,您会发现MVVM使情况变得更加糟糕,特别是对于初学者而言。 可能有多种方法来构建下面的UI,但是对于我们的讨论,让我们根据下图分离视图 : 闻到腥味……。 是的,对于MVVM的初学者而言,上述隔离可能是一个错误和时间杀手。 那么,MVVM将导致哪些问题: 管理多个嵌套视图和视图模型 。 通过驱动UI的不同业务逻辑查看可重用性。 (例如,单个CollectionTableCell用于具有不同业务逻辑的多个单元。) […]

MVC做对了

或一些想法,以更好地设计您的MVC应用 我一直在写有关MVP或MVVM之类的出色架构模式的文章,但是我们软件开发人员必须问自己一个非常重要的问题:我们是否按照预期的方式使用MVC? 我们是否真的研究过MVC还是只是使用了MVC?我们是在一些古老的Objective-C教程中学到的,只是将ViewControllers像神一样实现了所有功能? MVC:什么是MVC? 如果您了解自己的知识,并且不需要任何人提醒您有关MVC的全部信息,请随时跳到下一部分。 我将撰写有关MVC内容的简短概述。 MVC在1970年代开始在著名的Xerox Parc Alto Research实验室中使用。 当苹果家伙从Altos机器上窃取UI时,他们忘记了窃取MVC。 MVC提出的方案是将您的程序分为三层,这两层相互交互,从而自然地分离出软件的职责。 值得一提的是,MVC主要用于具有UI以及与该UI进行用户交互的应用程序。 例如,在后端实施这种模式没有多大意义。 另一个常见的错误是将整个程序视为MVC(实际上并没有错),而是一个更具哲学意义的问题,而不是一个具体的实现方法。 每个视图都应复制MVC三重奏,并且此组件应相互通信。 模型 :模型表示我们在应用程序中使用的抽象。 这可以是用户,销售,物品等。如果我们使用某种网络层,则模型可能在后端启动,并最终由我们的程序继承。 View :View代表实际的用户界面。在iOS / MacOS开发中,我们使用Xcode的Interface Builder(曾经是一个单独的工具,但在最近几年中已成为Xcode的一部分)创建Views。 尽管我们可能实际上并未编写View的代码, Controller :(或实际上是ViewController )如图2所示,这是Model-View-Controller模式的核心组件。 控制器是您应用程序内部结构的基础。 每个应用程序至少都有一个视图控制器,大多数应用程序都有多个。 每个视图控制器管理应用程序用户界面的一部分,以及该界面与基础数据之间的交互。 ViewControllers是我们实现MVC控制器部分的重要部分,但不是唯一的一部分。 我们将在本文中进一步讨论其他类型的Controller。 如Apple文档所述: 对于iOS应用程序,视图控制器提供了应用程序数据与其外观之间的重要链接。 了解何时以及如何使用视图控制器对于iOS应用程序的设计至关重要。 视图控制器是“模型-视图-控制器”设计范例中的传统控制器对象,但它们还有很多其他功能。 在iOS应用程序中,视图控制器提供了管理基本应用程序行为所需的大部分逻辑。 例如,视图控制器管理屏幕上内容的呈现和删除,并响应于设备方向的变化来管理视图的重新定向。 可以合并由和对象扮演的MVC角色,例如,使一个对象同时满足控制器和视图角色的要求,在该角色中,它被称为视图控制器。 MVC并不是真正地构建整个应用程序,它专注于与用户交谈时进行结构化以及用户如何使用它。 如果您正在使用数据库密集型应用程序,那么这可能不是最佳架构。 MVC在每个视图中实现 要牢记的一件重要事情(我实际上与我的一位同事进行过讨论,他的经验非常丰富,所以我想这可能会对其他人有所帮助)是MVC并不是您应用于应用程序的模式作为一个整体,而是在每个应用程序视图中重复执行的操作。 正如我们在一个假设的应用程序的图3上看到的那样,MVC模式在每个View上不断重复。 MVC面临着“大型视图控制器”综合症或问题:我们实际上拥有这些庞大的ViewController,它们可以处理所有事情:网络呼叫,业务逻辑,数据解析, 人类牺牲,猫狗共处……歇斯底里! 一切都交织在一起,解析器在解析完成后更新了UI(为什么不呢?) 如果这个问题没有道理,答案也不是:任何显然不是数据或显然是图形的东西都会被放入无定形的“控制器”集合中,这最终将整个代码库吸入内部,就像黑洞在其下方塌陷一样。自重” Graham Lee,Inside-Out Apps ViewControllers是您的朋友 避免使用这种可怕的,巨大的ViewController的一个好主意是让多个ViewController控制显示给用户的实际View,而不是使用一个由较小ViewController组成的复合ViewController,自iOS 5起可用 […]