翻译自:https://docs.swift.org/swift-book/LanguageGuide/Protocols.html 协议定义了适合特定任务或功能的方法、属性和其他要求的蓝图。...允许变量参数,但须遵守与正常方法相同的规则。然而,无法为协议定义中的方法参数指定默认值。 与类型属性要求一样,当在协议中定义static关键字时,您总是在类型方法要求前加上静态关键字。...只有在特定条件下,例如当类型的通用参数符合协议时,通用类型才能满足协议的要求。...编写试图采用SomeClassOnlyProtocol的结构或枚举定义是一个编译时错误。 注意 当该协议要求定义的行为假设或要求符合的类型具有参考语义而不是值语义时,请使用仅类协议。...textualDescription } } 为协议扩展添加约束 当您定义协议扩展时,您可以指定符合要求的类型在扩展的方法和属性可用之前必须满足的约束。
当这些详细信息在整个文件中使用时,使用文件专用访问来隐藏特定功能的实现细节。 私人访问将实体的使用限制为封闭声明,以及同一文件中该声明的扩展名。...单目标应用程序的访问级别 当您编写一个简单的单目标应用程序时,应用程序中的代码通常在应用程序中独立,不需要在应用程序模块之外提供。内部的默认访问级别已经符合此要求。因此,您不需要指定自定义访问级别。...只有当您希望实体成为框架API的一部分时,您才需要将其标记为开放或公共实体。 单元测试目标的访问级别 当您编写具有单元测试目标的应用程序时,应用程序中的代码需要提供给该模块才能进行测试。...协议 如果您想为协议类型分配显式访问级别,请在定义协议时这样做。这使您能够创建只能在特定访问上下文中采用的协议。 协议定义中每个需求的访问级别会自动设置为与协议相同的访问级别。...当您编写或扩展类型以符合协议时,您必须确保该类型对每个协议要求的实现至少与该类型对该协议的一致性具有相同的访问级别。例如,如果公共类型符合内部协议,则该类型对每个协议要求的实现必须至少是内部的。
Swift 泛型条件性符合(Conditional conformances) 表示泛型类型只有在其类型参数满足某些要求时才符合特定协议的概念。...在构建泛型适配器类型时,条件性符合尤其强大,泛型适配器类型旨在反映其类型参数的功能。...在swift3中,唯一的建模方法是使用不同的类型。...有了条件性符合,就可以提供一个泛型包装器类型,它的基本需求满足最小公分母(例如,Sequence),但是它可以用类型参数来扩展它们的功能(例如,当类型参数符合Collection时,LazySequence...现在,在Swift 4.1 以上,我们可以使得仅当它包含符合ScoreConvertible 协议的 Element 时,我们才使Array符合ScoreConvertible协议,就像这样: extension
这样做使您更容易对代码进行推理,并使Swift编译器能够优化您创建的集合的性能。 数组(Arrays) 数组将相同类型的值存储在有序列表中。相同的值可以在不同位置多次出现在数组中。...您还可以将数组的类型以速记形式写为[Element]虽然这两种形式在功能上相同,但速记形式是首选,并在参考数组类型时在整个指南中使用。...Sets 集合在集合中存储相同类型的不同值,没有定义的顺序。当项目顺序不重要时,或者当您需要确保项目只出现一次时,您可以使用集合而不是数组。...当您需要根据它们的标识符查找值时,您可以使用字典,就像使用现实世界的字典来查找特定单词的定义一样。...您还可以以速记形式将字典类型写为[Key:Value]虽然这两种形式在功能上相同,但简写形式是首选,并在参考词典类型时在整个指南中使用。
将项目迁移到Swift 3.0,新功能将不会破坏您的代码。不过,苹果已经在Xcode 8.3中支持Swift 2.3。所以如果你还没有从Swift 2.3迁移,现在是时候这样做了!...我建议您尝试在Playground上验证新的功能,以便更好地了解所有更改的内容。 Note:如果你想了解 swift 3.0 中的新功能,可以看这篇文章。...协议而在你使用StringProvider扩展可选的 wrapped 类型时,添加isBlank方法。...return Int(number) } #endif 然而,当使用Swift标准库时,这种方法有一个主要缺点。...它需要为每个受支持的旧语言版本编译标准库。这是因为当您以向后兼容模式运行Swift编译器时,例如您要使用Swift 3.0行为,则需要使用针对该特定兼容性版本编译的标准库版本。
您可以创建一个包含Int值的数组,或包含String值的数组,或者为可以在Swift中创建的任何其他类型的数组。同样,您可以创建一个字典来存储任何指定类型的值,并且该类型没有限制。...您可以通过在角度括号内写入要存储在堆栈中的类型来创建一个新的Stack实例。...您可以在创建自定义泛型类型时定义自己的类型约束,这些约束提供了泛型编程的大部分功能。像Hashable抽象概念根据概念特征而不是具体类型来描述类型。...在定义协议时,声明一个或多个关联类型作为协议定义的一部分有时是有用的。...上下文,其中条款 当您已经在泛型类型上下文中工作时,您可以编写一个泛型where子句,作为声明的一部分,该声明没有自己的泛型类型约束。例如,您可以在泛型类型的下标或泛型类型扩展中的方法上编写泛型子句。
定义类型铸造的类层次结构 您可以使用带有类和子类层次结构的类型转换来检查特定类实例的类型,并将该实例转换为同一层次结构中的另一个类。...但是,如果您迭代此数组的内容,则您收到的项目被键入为MediaItem,而不是Movie或Song。为了将他们作为他们的原生类型,您需要检查他们的类型,或将他们降为其他类型,如下所述。...当尝试将类型转换为子类类型时,类型转换运算符的形式返回一个可选值。item的结果as?Movie类型为Movie?,或“可选Movie”。 当应用于库数组中Song实例时,将向下转换到Movie失败。...仅当您明确需要它们提供的行为和功能时,才使用Any和AnyObject。最好具体说明您希望在代码中使用的类型。 以下是使用Any处理不同类型组合的示例,包括函数类型和非类类型。...Ivan Reitman // Hello, Michael 注意 Any类型表示任何类型的值,包括可选类型。如果您使用可选值,其中需要Any类型的值,Swift会向您发出警告。
当您开始自己的会话时,启动会话的玩家会创建一个ARWorldMap包含ARKit对游戏板周围区域的空间理解。加入会话的其他玩家会收到地图的副本,并查看主持人查看该表的照片。...枚举可以包含特定于每个游戏动作的附加信息(如弹弓抓取的状态或球发射的速度)作为每个枚举案例的相关值,这意味着您不需要在别处编写代码来确定哪些信息是相关的为哪个行动。...通过Codable在这些枚举类型上实现Swift 协议,可以轻松地序列化和反序列化操作,以便通过本地网络进行传输。...为了使用这种紧凑的位打包对结构进行编码和解码,SwiftShot定义了一种BitStreamCodable协议,扩展了Swift Codable协议的模式,并提供了一种将位流编码类型与Codable同一数据流中的其他...Swift 类型相结合的方法。
UserDefaults非常适合存储简单的设置,例如整数和布尔值,但是当涉及复杂数据时——例如自定义Swift类型——我们需要做更多的工作。...当使用这样的数据时,Swift为我们提供了一个很棒的协议,称为Codable:一种专门用于存档和取消存档数据的协议,这是一种“将对象转换为纯文本然后再次转换”的奇特方式。...我们将在未来的项目中更多地研究Codable,但是目前我们的需求很简单:我们想要归档一个自定义类型,以便可以将其放入UserDefaults中,然后在从UserDefaults中返回时将其取消存档。...当使用仅具有简单属性的类型(字符串,整数,布尔值,字符串数组等)时,支持归档和取消归档的唯一需要做的就是向Codable添加一致性,如下所示: struct User: Codable { var...该名称暗示它特定于JavaScript,但实际上,我们都使用它,因为它是如此的快速和简单。 Codable协议不需要我们使用JSON,实际上可以使用其他格式,但这是迄今为止最常见的格式。
当满足条件时使用带有break的repeat-while循环,在可读性、安全性和清晰度之间提供平衡。 承认解决这个问题类似于停止问题,并且编译器通常很难进行此类分析。...4) 讨论接受 Type 并返回该 Type 的实例的通用函数 问题 该问题是由于尝试在 Swift 协议函数中使用类型参数根据条件返回特定类型实例 (shadowFilter) 而引起的。...协议 ObjectRequestable 有一个方法 getObject(type: T.Type) -> T? 旨在返回特定类型的实例(如果在一致类中可用)。...编译器还会标记 ShadowFilter.self 的表达式模式与泛型类型之间的不匹配。 T 型。 这里的挑战在于尝试在协议函数内有条件地返回特定类型实例,而不需要直接类型转换。...当您获取 FooBar 实例上的属性 baz 时,它将 self 转换为 Bar,然后获取其 baz 属性。
如果您熟悉C,您将知道C枚举为一组整数值分配相关名称。Swift 中的枚举要灵活得多,不必为每个枚举案例提供值。...Swift 中的枚举本身就是一流的类型。它们采用了许多传统上仅由类支持的功能,例如计算属性以提供有关枚举当前值的更多信息,以及实例方法,以提供与枚举所代表的值相关的功能。...您通过在枚举名称后写入:CaseIterable来启用此功能。Swift将所有案例的集合公开为枚举类型的allCases属性。...当您首次在代码中定义枚举时,原始值设置为预填充值,如上面的三个ASCII代码。特定枚举情况的原始值始终相同。当您根据枚举的一个情况创建新常量或变量时,会设置关联值,并且每次这样做时都可能不同。...隐式分配的原始值 当您处理存储整数或字符串原始值的枚举时,您不必为每个案例显式分配原始值。当您不这样做时,Swift会自动为您分配值。
这意味着您应该能够扩展您的类型的功能,而无需大幅更改它们以添加您需要的内容。 3. Liskov Substitution 程序中的对象应该可以用它们的子类型的实例替换,而不会改变该程序的正确性。...在设计将在代码中的不同位置使用的协议时,最好将该协议分解为多个较小的部分,每个部分都有特定的作用。这样,客户端只依赖于他们需要的协议部分。 5....代码的不同部分不应依赖于具体的类。他们不需要了解这些。这鼓励使用协议而不是使用具体的类来连接应用程序的各个部分。 注意:当您重构现有项目时,按顺序遵循 SOLID 原则并不重要。...Creating the Enum 在您的项目导航器中,创建一个名为 Enums 的新组。在其中创建一个名为 ReportRange.swift的新文件。...拥有这样的特定协议将使将来更改功能变得容易,并使测试这些新功能变得更加容易。当你有少量代码时,最好现在就这样做,而不是等到项目变得太大而变的棘手。
下载 Xcode 14 Beta 版[4] 提案 通过的提案 SE-0352: 隐式开放的存在类型[5] 状态:Swift 5.7 已实现Swift 中的存在类型允许存储一个特定类型为未知的值,且可能在运行时更改...被存储值的动态类型,我们称为存在类型的底层类型,仅由它遵循的协议集以及潜在的超类知道。尽管存在类型对于表达动态类型的值非常有用,但由于它们的动态性质,它们受到一定限制。...第二次审查的重点是关注向前兼容性,当一个调用唤起一个隐式开放的存在类型,必须被抹除类型以防止存在的动态类型内存泄漏到返回值中。...当存在类型的表达能力增加,我们可能会有能力使用一个更具体的类型作为这一个调用的返回类型,这可能造成源中断。...与泛型一样,它们使函数能够获取和返回多种可能的类型。与泛型参数类型不同,存在类型在作为输入传递给函数时不需要预先知道。此外,当从函数返回时,可以删除具体类型(隐藏在协议接口后面)。
使用原始的 withTaskGroup() API 时,可能会出现一个问题,因为 Swift 只在我们调用 next() 或遍历任务组的子任务时才丢弃子任务及其结果数据。...Type SE-0309 极大地放宽了 Swift 在协议具有 Self 或关联类型要求时禁止使用协议作为类型的限制,转向一个仅基于它们所做的特定属性或方法受限的模型。...Self 要求的协议,这意味着它提供了引用采用它的特定类型的功能。...:当创建缓存时,我们显然可以直接创建一个特定的缓存,如下所示: func loadDefaultCache() -> LocalFileCache { LocalFileCache(items:...将这些称为存在类型:您正在使用的实际数据类型位于一个盒子内,当我们在该盒子上调用方法时,Swift 理解它应该隐式地在盒子内的数据上调用方法。
它们是用于访问特定语言功能的符号,这些功能会生成与命名属性相关的内容,而不是正常访问该属性。...Swift 在前缀运算符位置中使用 \ 来创建“关键路径”,该对象通常表示(在本例中)Graphic.children 属性,而不是特定 Graphic 的 Children 属性;该对象可以应用于 Graphic...该功能的演变提案实际上讨论了几种不同的语法,并解释了为什么选择反斜杠[4]。 前缀意味着您正在访问相关属性的属性包装器提供的特殊功能。...这是阻止我们在 Swift 中完全完成对仅移动 C++ 类型的支持的一个关键问题,因为我们需要形成像 UnsafePointer 这样没有语言限制的类型。...此外,以下语言功能将有助于改善 Swift 中对 C++ 类型执行的一些常见操作的人体工程学: 能够在 Swift 序列上执行借用 for 循环,这确实需要经过 IteratorProtocol,但可以使用索引迭代
全局函数 Global functions :无需特定类型范围就可以从任何地方访问的函数是一个古老的概念,在 C 和 Objective-C 等语言中很流行,但是在 Swift 中不建议使用,因为我们希望对它们进行很好的类型化和范围划分...global function 由于历史原因,Swift 标准库中仍然具有相当多的公共全局功能,其中一些功能至今仍然非常有用。让我们看一下zip()和dump()之类的函数。...如果您需要同时迭代两件事,这将非常有用,因为如果没有zip,则必须手动构建一个for循环并分别访问每个数组中的每个索引。使用zip可以使您以更实用的for-in方式访问所有数组中的元素。...) 同样非常流行的是,将stride()函数添加到Swift中,作为一种创建可以跳过某些元素的循环的方法,因为从swift 语言中删除了等效的 C 样式方法: for (int i = 0; i < 10...本文未在本节中单独提及,因为如果需要交换数组元素,则使用的正确方法是Array.swapAt()。但是,在需要创建伪“aux”属性来保存值的其他情况下,仍然可以使用swap()。
在上面的示例中,index是一个常量,其值在循环每次迭代开始时自动设置。因此,index在使用之前不必声明。它仅通过包含在循环声明中来隐式声明,而无需let声明关键字。...但是,您可以使用此语法迭代任何集合,包括您自己的类和集合类型,只要这些类型符合Sequence协议。 While循环 while循环执行一组语句,直到条件变成false。...当第一次迭代开始前不知道迭代次数时,最好使用这些类型的循环。Swift提供了两种类型的while循环: while在每次通过循环开始时评估其状态。...如果玩家在正方形25上移动或超过25,循环的条件将计算为false,游戏结束。 在这种情况下,while循环是合适的,因为while循环开始时游戏的长度不明确。相反,循环被执行,直到满足特定条件。...条件声明 根据特定条件执行不同的代码通常非常有用。您可能希望在发生错误时运行额外的代码,或者在值变得太高或太低时显示消息。为此,您可以将部分代码附加条件。
这些被称为常数,比C中的常数强大得多。在整个 Swift 中,常量会使用,使代码在处理不需要更改的值时更加安全、更清晰。...仅使用变量来存储需要能够更改的值。 类型注释 您可以在声明常量或变量时提供类型注释,以明确常量或变量可以存储的值类型。...注意 仅当您特别需要与平台原生单词大小相同的无符号整数类型时,才使用UInt。如果不是这样,最好是Int,即使已知要存储的值是非负值。...由于类型推断,Swift需要的类型声明比C或Objective-C等语言少得多。常量和变量仍然是显式类型,但指定其类型的大部分工作都是为您完成的。 当您声明具有初始值的常量或变量时,类型推断特别有用。...在Objective-C中,’ nil ‘是一个指向不存在对象的指针。在Swift中,’ nil ‘不是一个指针——它是一个特定类型的值的缺失。
领取专属 10元无门槛券
手把手带您无忧上云