Tag: 协议

在Swift类扩展中使用Self

在扩展类时,将Self用作参数类型可能很诱人,但是Swift只允许在协议中或作为类方法调用的结果来使用它。 实际上,在大多数情况下,这是非final类在语义上正确的限制,除非我们要使用Self作为闭包的参数,例如考虑完成处理程序。 在这种情况下, Self用作另一个方法调用结果,这是绝对有效的选项。 我最喜欢的示例是Operation类的延续帮助器: 使用继续操作而不是完成块可以控制其执行上下文。 我倾向于在Operation子类中定义结果访问器,而我通常希望连续地访问它们。 从延续中访问操作不会引入保留周期,因为任何操作都已经拥有其依赖项。 因此,我们需要传递刚刚完成执行的块接收操作作为参数。 这在类扩展中是不允许的。 嗯,但是我们可以在协议中以这种方式使用Self ,对……救援协议! 计划是定义一个虚拟协议,使我们的类符合该协议,并扩展该协议而不是该类。 现在我们可以以类型安全的方式使用continue(on:with:)扩展和访问操作结果: 感谢您的宝贵时间,并希望本文对您有所帮助。 如果您觉得本文有用,请不要忘记to。

在您的ViewController中使用多个tableView或CollectionView

曾几何时,我为一个项目编写代码,该项目的第一页中有很多表和集合视图。 我记得我曾经用“容器视图”解决了这个问题,但这是一个错误的决定……。 另一个好用的选择是“滚动视图” ,它很容易实现,但操作起来又费时。 由于委托是一个协议,我认为有一个好的方法…… 协议和代表示例 协议和委托示例–在一个ViewController中使用多委托 github.com 首先创建一个NSObject类,以减少自定义,然后添加要用作超类的所有委托方法。 将Model属性添加到您的类中以进行设置并获取所有要显示的信息。 在我的情况下,数据模型名称为ItemManager。 创建一个dataModel类,并将其分配给您的DataProvider的Model。 自定义所有方法并设置DataModel之后,是时候将类设置为UITableView或UICollectionView的协议了。 使用Techniq的好处还在于您可以在应用程序中使用单元测试,我真的建议您阅读使用Swift 4进行测试驱动的iOS开发–第三版作者:Dominik Hauser博士 使用Swift 4进行测试驱动的iOS开发–第三版– PDF电子书| 现在只要$ 5 使用测试驱动的方法通过Swift 4和Xcode 9开发功能强大的iOS应用 www.packtpub.com

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() […]

使用Swift协议提高代码质量

因此,您正在与许多团队成员一起从事一个项目,或者您正在编写一个框架。 两者都涉及编写其他开发人员最有可能查看或以某种方式使用的代码,无论是添加新功能还是从外部访问您的功能。 如果您是独立工作,很容易养成一个坏习惯,即直接跳入编写实现并随手进行即兴创作,而只是在同一周晚些时候回来,发现您或您的任何同事都可以什么都没读。 这将导致新功能需要花费更长的时间添加,团队内部混乱,并且在某些情况下可能最终会完全重写整个功能。 请记住,评论不应该只是为自己写。 其他人会阅读您的代码,因此当您编写注释时,请确保对他们和您自己有意义,几周后再返回。 您可以通过遵循一些黄金法则来实现。 不做任何假设 : 不要以为其他开发人员会像您一样了解该项目。 请勿使用其他人似乎看不见的短语。 如果花时间检查外部依赖关系和潜在的副作用,则会浪费大量时间。 如果您发现自己在写小说来解释单个功能,那么您的功能可能做得太多。 也许您应该将功能分解为几个较小的功能。 保持清楚: 删除多余的单词和短语,但不要删除太多,以免短语变得模棱两可。 注释应清楚简洁地说明代码的作用。 不要说它是什么,要说它 做 什么 : 例如,我们都已经看到了注释,这些注释准确地描述了该函数的含义:但是没有解释其作用。 我们知道它会返回一个字符串数组 您可能正在看函数的实现,以查看函数实际执行的操作,但您不必这样做。 这些评论应该告诉您您需要知道的一切。 我们可以使其他开发人员更容易阅读。 使用cmd + option + /, Xcode可以让我们为此功能生成一个不错的注释结构,并且可以对其进行改进。 因此,我们现在有了一个很好的注释功能。 现在,我们想为User对象添加更多功能,因此我们创建了UserService 。 可以将其保留为一个初学者项目的原样,但是当您编写自己的框架或从事商业项目时,这仅仅是不够的。 代码需要是可单元测试的,也许某些实现代码需要具有受限的访问权限。 使用协议将为项目带来很多好处。 我们希望使我们的UserService更具可读性,因此让我们为其创建一个Protocol ,恰当地命名为UserServicing 如果UserService符合UserServicing ,则可以这样使用: 那么,什么使它更好呢? 没有实现代码:没有干扰性的实现代码,加上高质量的注释,您可以更清楚地看到每个功能的职责以及整个Servicing的功能。 依赖注入+测试:通过使用协议,这意味着我们可以更改符合UserServicing的任何内容的实现,而不会产生任何负面影响。 这意味着我们可以使用Cuckoo之类的库对协议实现进行模拟,存根和测试 。 灵活性:如果我们的User数据提供程序发生了更改,或导致UserService内的实现发生更改的其他任何内容,都没有关系! 只要UserService的定义保持不变,就无需更改ViewModel中UserService的实现。 在开始任何实施之前,请先编写注释良好并记录在案的协议。 通过让您事先考虑所有功能要求,它将确保重点,并有助于获得更好的画面。 此外,如果将代码以有组织的方式分解为协议,它还允许项目的新开发人员或使用您的框架的人员快速了解代码的工作方式。 感谢您抽出宝贵的时间阅读。 如果您有任何疑问或有兴趣阅读我的其他文章,请随时在Twitter或LinkedIn上与我联系。

快速了解所有协议

资源 : 苹果文件 协议定义了适合特定任务或功能的方法,属性和其他要求的蓝图。 然后,该协议可以由类,结构或枚举采用,以提供这些要求的实际实现。 满足协议要求的任何类型都被称为符合该协议。 因此,简单起见,一个协议会说一个struct,class或enum,如果您想成为THAT ,请执行此操作,然后再执行此操作。 例如:如果您想成为人类,则必须饮食,睡眠和休息。 类,结构体,枚举可以通过将协议名称放在类型名称后(用冒号分隔)作为其定义的一部分来采用这些协议。 可以列出多个协议,并用逗号分隔: 如果一个类具有超类,请在其采用的任何协议之前列出超类名称,然后用逗号: swift和Objective-C都支持多级继承。 它只能有一个单一的基类。 两者都不支持多重继承。 如上图所示,仅支持协议的多个继承,以逗号分隔。 您可能已经看到UIViewController的实现UITableview datasource和delegate协议。 class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { } 虽然,最佳实践是将其分组在ViewController的单独扩展中并实现协议。 class ViewController: UIViewController {} extension ViewController: UITableViewDataSource, UITableViewDelegate //implement protocol methods ands variables here.. extension ViewController: UITableViewDataSource, UITableViewDelegate //implement protocol methods ands variables here.. 协议可以具有属性以及符合该协议的类,枚举或结构可以实现的方法。 协议声明仅指定所需的属性名称和类型。 它没有说明该属性是存储的还是计算的。 协议还指定每个属性必须是可获取的还是可获取的和可设置的。 属性要求始终声明为变量属性,并以var关键字为前缀。 […]

Swift中数组的受限扩展

协议和扩展是快速发展的组成部分。 到目前为止,您可能已经使用了很多时间。 您可能出于各种原因为您的班级或结构创建了扩展。 这里我将给出一些示例,其中您可以为几个现有的类进行扩展。如果你们还记得在Objective-C上工作,那么您将与Catagories交叉。 在这里,约束扩展是一种类别,您可以在不知道其内部工作的情况下扩展现有对象的功能。 在这里,我将以数组为例,数组是同质元素的集合,在进行实时项目时,您需要处理很多需要不断操作的数组,您可以提出扩展一样的 字符串数组 让我们假设一个场景,其中您有一个字符串数组,并且需要事先存储少量数据,例如 总字符数 字数 每个单词中的字符数 让我们来看一个数组示例,如下所示 let arrayString:[String] = [“教父”,“肖申克的救赎”,“辛德勒的名单”,“愤怒的公牛”,“乱世佳人”,“绿野仙踪”,“阿拉伯劳伦斯”,“阿甘”] 现在,假设您在整个项目中具有与上述所需的实现相同的数组。 为了避免重复并扩展现有Array的功能,我们可以编写如下扩展 通过在Array上实施受约束的扩展,您可以轻松避免代码重复,并且Array操作很容易。 让我们继续测试实施 让characterCount = arrayString.totalCharacterCount() 让wordCount = arrayString.wordCount() 让eachCharacterCount = arrayString.elementCharacterCount() 打印(“ characterCount = \(characterCount)”) 打印(“ wordCount = \(wordCount)”) print(“ eachCharacterCount = \(eachCharacterCount)”)//这将打印characterCount = 128 wordCount = 22 eachCharacterCount = [13、24、16、11、18、16、18、12] 这是数字的另一个例子 这是数字数组的另一个例子 在上面的示例中,这里以计算为例 数组元素的总和 将数值数组转换为字符串数组 这可以在任何数字数组上无缝运行,但在数组中的其他元素上同样会出错。 […]

Swift协议:属性区别(获取,获取设置)🏃🏻‍♀️🏃🏻

面向协议的程序设计是iOS中的新趋势,尽管它是迅速引入的,但它已经有几年历史了。 Swift是一种新时代的语言,并且在每次迭代中都变得越来越强大。 在2015年的WWDC中,我们都遇到了Dave Abrahams的Crusty,他解释了POP的重要方面。 我真的建议您仔细阅读一次,以更好地了解POP。 Swift中面向协议的编程– WWDC 2015 –视频– Apple Developer Swift的设计核心是两个令人难以置信的强大创意:面向协议的编程和一流的价值…… developer.apple.com 我还建议阅读Raywenderlich的教程Niv Yahel撰写的POP简介,它也可以在操场上进行讲解和实际操作。 协议定义了适合特定任务或功能的方法,属性和其他要求的蓝图。 然后,该协议可以由类,结构或枚举采用,以提供这些要求的实际实现。 满足协议要求的任何类型都被称为符合该协议。 苹果文件。 协议SomeProtocol { var mustBeSettable:Int {获取设置} var didNotNeedToBeSettable:Int {get} } 协议声明一致性类型必须通过在声明主体中包含协议属性声明来实现属性。 它具有变量声明的特殊形式: Var propertyName:类型{获取设置} 与其他协议成员声明一样,这些属性声明仅声明符合协议的类型的getter和setter要求。 因此,您不能直接在声明它的协议中实现getter或setter。 可以通过多种方式通过符合类型来满足吸气剂和设置剂的要求。 如果属性声明同时包含get和set关键字,则符合条件的类型可以使用存储的变量属性或既可读又可写的计算属性(即,同时实现getter和setter的)来实现它。 但是,该属性声明不能实现为常量属性或只读的计算属性。 如果属性声明仅包含get关键字,则可以将其实现为任何类型的属性。 有关实现协议的属性要求的符合类型的示例,请参见属性要求。 对于Gettable Protocol Properties ,可以通过任何种类的属性来满足要求,并且对于可用于您自己的代码的属性,也可以设置该属性是有效的。 对于“可获取和可设置的协议属性” ,不能通过始终存储的属性或只读的计算属性来满足要求。 协议中的属性要求始终被声明为变量属性,因为它们被声明为计算属性。 Gettable —常量属性 协议FullyNamed { var fullName:String {get} } struct […]

Swift有多快以及为什么(第3部分)

在第1部分中,我们知道在一个非常简单的情况下,Swift可能比Objective C快9倍。这是一个巨大的改进。 在第2部分中,我们知道可以在编译时优化C函数。 编译器可以将某些函数调用替换为值。 C ++具有称为模板元编程的能力。 但是对于大多数实际使用案例,Swift的速度与C相当。 现在,该看看Swift在复杂情况下是否可以保持其速度。 在这里,我们有一个Swift类Calculator ,一些类都继承自它,并稍微改变了add行为。 我知道“慷慨”并不意味着给出夸大的加法结果。 但是我什至不会使用那些新类。 因此,不会造成任何伤害。 和往常一样,Swift选择内联这些函数(即使add函数也被标记为重写。)但是这一次,由于有4种不同的add函数,Swift需要每次都找到正确的代码块来运行。 红线描述了执行流程。 因此,对于每个循环,CPU需要执行比较分支分支,因此速度较慢。 在这种情况下,我们很幸运。 由于我们正在使用Calculator.add ,因此它是第一个。 调用SuperGenerousCalculator.add需要更长的时间来执行,结果数据显示出这一点。 我们可以确定要调用哪个函数,因为我们知道它是同一对象,因此应始终调用Calculator.add 。 无需每次检查。 但是,尽管功能强大,但是Swift编译器有其局限性。 有一个称为面向协议的编程的新工具。 它促进使用protocol和struct 。 这也使某些事情变得简单,并避免了与类相关的性能损失。

使用默认参数解密Swift协议扩展

所以我们可以说 如果变量推断类型为Protocol ,则将始终调用该方法的动态实现。 否则 ,将调用该方法的协议实现, 除非该方法不覆盖默认参数。 我与您分享了所有这些情况的操场片段: protocol TheProtocol { func method1(text: String) } extension TheProtocol { func method1(text: String = “default1”) { print(“Called method1 from TheProtocol: \(text)”) } func method2(text: String = “default2”) { print(“Called method2 from TheProtocol: \(text)”) } } struct Struct1: TheProtocol { func method1(text: String = “default1”) { print(“Called method1 from […]

Swift中泛型和协议一致性的功能。

在Swift协议和泛型中可以很好地协同工作,实际上有一个术语可以简化这种关系。 它被称为DRY(不要重复自己),它的意思是:使用抽象避免重复。 因此,在这里,我将向您展示泛型在Swift中的强大功能以及协议一致性如何提升泛型。 让我们看一下以下示例: 假设您要确定两个条件是否相等。 编写一个函数,该函数返回一个布尔值以根据我们正在比较的两个事物是否相等来返回true / false。 例如,让我们编写一个函数来测试两个整数值是否相等: 太酷了,现在可以测试两个整数是否相等,但是无法测试其他类型,例如Double’s,Floats和其他可以相等的Swift类型。 因此,使用Swift中的泛型以及协议一致性,我们可以做到这一点: 哦哦 ,现在发生了什么? 为什么会出现错误? 该错误是由于以下事实造成的:T是泛型类型,并且未知它是否可以相等。这就是协议一致性起着重要作用的地方。 因此,我们强制等于函数仅采用相等的参数类型。 这就是我们在Swift中可以做到的方式: 要么, 从上面的代码片段中可以看到,泛型和协议一致性如何真正帮助您避免编写重复的代码。 如果您开始在代码库中更频繁地使用泛型和协议,这是一个好习惯。 它肯定会简化您作为开发人员的生活。