Tag: 泛型

Swift中函数的通用专业化

在今天的帖子中,我们将讨论Swift编译器的Generic专业化知识,并对它是什么以及SIL Optimizer为什么执行此操作以获得更高性能的代码进行基本概述。 此外,我们还将简要介绍Swift中间语言(SIL)表示形式以及它在此通用专业优化遍历中的作用。 首先… 编译器 在深入研究泛型专长之前,我们需要至少从高层次上了解有关编译器流程的一些知识。 swift编译器获取您的Swift代码,将其处理为手动编码的Lexer,将其标记化并将其转换为抽象语法树(AST),然后是语义分析(Sema),其中编译器将使用解析器生成的AST并进行类型检查的AST并检查其中的语义问题。 然后,Swift中级语言生成(SILGen)阶段将通过语义分析生成的AST转换为他们所谓的原始SIL,在对SIL进行了一些优化(如通用专业化,ARC优化等)之后……它生成了这种被称为规范SIL的优化SIL。然后将其交给IRGen生成中间表示(IR),该中间表示将传递给LLVM,以使其继续工作并生成目标文件(.o),该文件随后将由链接器粘合在一起并生成最终的二进制文件。 这是对编译器管道的简要概述。 这只是让我们了解编译器的各个阶段,但是在这里,我们将重点介绍发生通用专业化的SILGen和SIL Optimization Pass。 仅供参考,Swift中间语言(SIL)是一种静态单分配形式(SSA形式)中间表示形式,用于实现swift编译器,目的是在源代码与LLVM IR之间架起抽象桥梁,从而提供一种执行高级别的优化,例如通用专业化,保留/发布优化,动态方法去虚拟化等等……以及高级诊断分析。 您可以在快速主存储库的说明文件[1]中找到有关SIL的更多信息。 返回通用专业化 因此,泛型专业化是SIL优化过程,它分析了对泛型函数的所有调用(使用完整模块编译模式时在模块中)或具有@_specialize属性的泛型代码(我们将在后面讨论),然后生成新的特殊化这些函数的版本将泛型的所有专用用法替换为直接调用生成的专用函数。 使用专用函数的性能更高,因为它可以使用特定的具体类型最有效的布局,并且在诸如将参数复制到局部变量之类的操作中,例如,它避免了动态分配泛型类型和保存对运行时类型元数据大小和对齐方式的值见证表。 让我们看一下如何生成专用SIL的实际示例 生成的SIL上还有很多其他内容,但仅突出显示与我们定义的函数相关的内容。 仅查看生成的SIL,我们就可以看到编译器如何发出通用和专用SIL表示形式。 我们可以注意到,主SIL调用了函数@ $ S4main9incrementyxxs13BinaryIntegerRzlFSi_Tg5的引用,正如我们看到的那样,它是增量的专用版本。 这意味着主要功能正在调用优化的专用功能。 另外,我们可以注意到专用版本针对Int进行了完全优化,而在通用SIL上,所有操作都基于基于元类型信息的调用(应用)函数。 告诉SIL优化器不执行专业化 我们可以告诉编译器,由于某种原因,我们不希望使用@_semantics属性对该通用函数进行专用化。 您可以在HighLevelSILOptimizations文档的“优化语义”属性部分中找到有关语义的更多信息。 这就是本文的全部内容\ o / 如果您有任何意见或疑问,请告诉我。 您的反馈意见非常重要,因此我们可以改善此问题以及将来的帖子,很高兴收到它:)) 您可以在Twitter上@ LucianoPassos11找到我。 感谢您阅读🙂 参考文献 Swift中级Languange(SIL)。 https://github.com/apple/swift/blob/master/docs/SIL.rst SIL程序员手册。 https://github.com/apple/swift/blob/master/docs/SILProgrammersManual.md 泛型。 https://github.com/apple/swift/blob/master/docs/Generics.rst SIL中的高级优化。 https://github.com/apple/swift/blob/master/docs/HighLevelSILOptimizations.rst

Swift Generics的力量-第1部分

泛型函数,泛型类型和类型约束 当他们工作时,您爱他们,当他们不工作时,您恨他们。 😀😀 在现实生活中,每个人都知道仿制药的功效:早上起床,决定喝什么,加满杯子☕️ Swift是一种类型安全的语言。 每当使用类型时,都需要指定它们。 例如,我们需要一个可以处理多种类型的函数。 Swift已经提供了Any和AnyObject但是除非必须使用,否则最好不要使用它们。 使用Any和AnyObject将使我们的代码易碎,因为在编译期间我们将无法捕获类型不匹配的情况。 泛型是我们需求的解决方案。 通用代码允许您编写可重用的函数和数据类型,这些函数和数据类型可与任何与您定义的约束匹配的类型一起使用,同时提供编译时类型安全性。 它使您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。 例如,诸如Array, Set and Dictionary类型的类型在该元素上是通用的。 假设我们必须打印整数和字符串数组。 我可以创建2个函数来完成这项工作。 让intArray = [1,2,3,4] 让stringArray = [a,b,c,d] func printInts(array:[Int]){ print(intArray.map {$ 0}) } func printStrings(array:[String]){ 打印(stringArray.map {$ 0}) } 现在,我必须打印浮点数数组或自定义对象的数组。 如果我们看一下上述功能,则所使用的类型只是区别。 因此,无需重复代码,我们可以编写可重用的泛型函数。 泛型函数可以使用由占位符类型T标识的任何类型。占位符类型名称并没有说明T必须是什么,但是它确实说两个array必须是T类型,无论T代表什么。 每次调用print(_:)函数时,都会确定要代替T使用的实际类型。 func print (array:[T]){ 打印(array.map {$ 0}) } 上例中的占位符类型T是类型参数。 通过在尖括号内用逗号分隔多个类型参数名称,可以提供多个类型参数。 如果我们看一下Array 和Dictionary ,它们有一个命名的类型参数,即Element&Key,Value,它说明类型参数与它所使用的泛型类型或函数之间的关系。 注意:始终为类型参数提供大写的驼峰名称(例如T和TypeParameter ),以表明它们是类型的占位符,而不是值。 […]

Swift中的泛型函数

泛型是Swift最强大的功能之一,许多Swift标准库都是使用泛型代码构建的。 Swift 4语言提供“通用”功能来编写灵活且可重用的函数和类型。 泛型用于避免重复并提供抽象。 现在让我们看看快速语言中泛型函数的用法以及如何使用它。 例如,考虑使用以下程序交换值。 如果我们看上面的程序,该函数仅接受Int值。 因此,如果我们要编写用于接受“ String”或“ Double”值的函数,则必须编写两个类似的函数,用“ String”或“ Double”替换“ Int”。 因此,如果我们要编写一个接受任何类型的函数(无论是Int , Double还是String) ,该怎么办。 ? 为此,我们需要编写通用函数。 如何编写泛型函数? Swift 4提供作为通用类型参数名称 func swapTwoValues(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA } swapTwoValues(_:_:)函数的主体与swapTwoInts(_:_:)函数的主体相同。 但是, swapTwoValues(_:_:)的第一行与swapTwoValues(_:_:)略有不同。 以下是第一行的比较: func swapTwoInts(_ a: inout Int, _ b: inout […]

在Swift 4.2中验证textField输入的通用方法

为了创建通用验证类,我将使用可变参数,元组,正则表达式和枚举。 枚举是迅速开发人员的强大工具。 我们将从Alert,Valid,ValidationType,RegEx,AlertMessages的枚举开始。 现在,最后我们将做最后一个枚举,以返回验证失败消息。 现在,我们完成了使用枚举设置所有自定义参数类型的操作。 比赛结束了一半。 成为NFS Player,开始建立共享类进行验证,以加速完成比赛。 现在,我们完成了您的通用验证文件。 享受快乐编码🙂 仅需一秒钟,就可以通过两个示例快速了解如何使用此验证类。 拍手,如果您喜欢这篇文章并关注我… Github回购链接:-https://github.com/SandeepSpider811/ValidationExampleSwift 您可能感兴趣的其他文章: #iOS中的3D Toch Peek和Pop #动态的附件视图高度 #验证UITextField响应者的通用方法 #使用.xcconfig文件在Xcode Project中存储各种SDK密钥和ID。 #Xcode中的颜色资产(.xcassets)。

Swift中的泛型

泛型编程是一种灵活地编写可重用函数和类型的方法 它的特点是快速,许多通用的标准libaray快速构建。 让我们了解它解决了现有问题 上面的函数使用引用传递来交换两个Int,现在,如果我需要编写一个可以交换字符串的函数,我将再编写一个如下所示的函数 如您所见,两个函数的实现主体相同,唯一的区别在于参数的类型。 现在让我们看看泛型如何解决上述双重代码 那就是我们交换两个值的通用函数的样子, 在功能名称之后 指示这是一个通用函数,其参数类型为T 函数参数列表包含类型为T而不是Int,Double或String,将替换为实际类型 下面的代码显示了上面的通用函数swapTwoValues如何用于swapTwoValues Strings,Int值。 因此,这就是泛型,泛型功能的快速介绍。 我们将涵盖的主题将进一步阅读 通用类型 类型约束到通用函数/类型 关联类型 不出所料,是的! 您可以快速编写通用类型,我们日常使用的最常见类型Array , Dictionary是通用类型 让我们深入研究代码,无需任何进一步的理论 上面的结构IntStack使用数组来推入并弹出Int项以进行堆栈,而push() & pop()函数正在更改,因为它们正在修改结构项数组。 现在让我们看看我是否需要一个通用类型,该通用类型不仅可以推入和弹出Int项目类型,还可以推入和弹出其他类型。 差别不大吗? 结构名称后面附加通用语法 ,其中Element是一种类型,将用实际的类型(Int,Double,String等)替换 在三个地方用作占位符的Element 用Element类型的值数组初始化的属性items push()函数采用类型为Element的参数 函数pop()返回值是Element类型 上面的代码显示了我们如何使用通用Stack推入和弹出类型为String和Int的项目。 扩展通用类型 上面的代码片段是其中类型为topItem的值类型Stack的扩展,其中topItem为Element类型,如果stack为空则返回topItem ,否则返回最后一个项目。 我们可以迅速对可与泛型函数和类型一起使用的类型施加某些类型约束 没得到吗? 让我们阅读下面的行,然后尝试再次映射它。 我们可以使用以下规则定义通用功能或类型, 使用的类型应始终确认特定的协议或协议组成 使用的类型应从特定的类继承 例如,在Swift的Dictionary字典的键必须始终与协议Hashable确认,否则不能用作Dictionary键 让我们看一下带有类型约束的泛型函数 语法指示泛型函数将采用仅向协议Equatable确认的类型 默认情况下,所有数据类型String,Int,Double等都向协议Hashable确认, Equatable协议确认Equatable协议,因此上述代码可以正常工作。 让我们等不及看到具有类型约束的泛型类型 ,将创建一个NavigationControllerStack来推送和弹出属于UIViewControllers或其子类的viewcontrollers。 那就是NavigationControllerStack样子,类名称后的语法表示,只有从UIViewController继承的此类,该类才会采用Element 。 在上面的代码片段中,我们创建了一个从UIViewcontroller继承并推送到NavigationControllerStack PeopleViewController实例,与从UIViewcontroller继承的PeopleViewController实例推送的方式相同。 在这里,我们将看到如何在协议中使用泛型。 […]

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

在Swift中使用泛型配置多个单元格

iOS开发人员将大部分开发时间用于处理UITableView和UICollectionView。 当您需要显示具有相同数据类型的列表(例如用户列表)时,这非常简单。 但是,如果您需要在一个表视图中显示一堆不同的单元格呢? 这可能导致真正的混乱! 让我们想象以下情况。 我们需要显示具有不同类型单元格的提要; 它可以是UserCell , CommentCell , ImageCell等。 最明显的解决方案是在方法tableView(_:cellForRowAt :)中创建if语句,其外观如下所示。 希望该解决方案能对您的项目有所帮助。 示例项目在GitHub上可用。 谢谢阅读。

iOS 2018系列:破解iOS采访或成为iOS专家(8)

快速的泛型和LRU缓存 我们将通过此博客学习Swift和LRU算法中的泛型。 当您的面试官要求您在纸上编写通用LRU缓存的代码时,对于iOS开发人员来说,这是第3轮或第4轮的热门问题,根据面试官的知识,实现语言可能会有所不同……哈哈哈! 希望你有一个好的面试官🙂 通用 代码使您可以编写灵活,可重用的函数和类型,这些函数和类型可根据您定义的要求与任何类型一起使用。 泛型函数 func swapTwoValues (_ a:inout T,_ b:inout T){ 令tempA = a a = b b =温度 } 该函数的通用版本使用占位符类型名称(在这种情况下称为T ),而不是实际的类型名称(例如Int , String或Double )。 占位符类型名称并没有说明T必须是什么,但它确实说a和b必须具有相同的T类型,无论T代表什么。 每次swapTwoValues(_:_:)函数时, swapTwoValues(_:_:)确定要代替T使用的实际类型。 泛型函数和非泛型函数之间的另一个区别是,泛型函数的名称( swapTwoValues(_:_:) )后跟尖括号( )中的占位符类型名称( T )。 方括号告诉Swift, T是swapTwoValues(_:_:)函数定义中的占位符类型名称。 因为T是一个占位符,所以Swift不会查找名为T的实际类型。 在大多数情况下,类型参数具有描述性名称,例如Dictionary Key和Value和Array ,它向读者介绍类型参数与其所使用的泛型类型或函数之间的关系。但是,当它们之间没有有意义的关系时,通常使用单个字母(例如T , U和V来命名它们,例如下面的class中的T 除了编写有关泛型的理论外,我们不妨看一下用例,但对于那些需要更多详细信息的人,请参考本文下面给出的链接。 为什么我们需要LRU Cache,甚至是通用的。为什么? 让我们考虑一下它在我们的应用程序中的使用。 显示基于用户使用情况的列表。 基于用户使用情况的功能顺序。 应用程序设置选项基于它的频繁使用。 根据用户的应用使用情况在Android手机上创建触摸biz屏幕。 在列表视图中显示大量图像 将大文本内容加载到内存中 […]

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

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