在学习 SwiftUI 的过程中,发现对标题中的内容还不甚熟悉,而这些内容是 SwiftUI 中极其重要的部分,不理解就很难熟练地掌握 SwiftUI,故温习并记录,以下内容可视为官方教程的简装版。
协议
定义
协议规定了实现某一特定功能的方法和属性。
类、结构体、枚举类型都可以遵循协议。
语法
1 | protocol SomeProtocol { |
属性要求
属性可以是存储型或计算型,必须明确其可读写性。
1 | protocol Cat { |
方法要求
方法可以是实例方法或类方法,方法参数不能使用默认值。
异变方法要求
协议中的实例方法可以标记为 mutating
,当结构体、枚举这样的值类型实现相应的方法时,需要加上 mutating
关键字,而类作为引用类型,不需要该关键字。
初始化器要求
协议可以要求遵循者实现指定的初始化器,只是不需要写初始化器的实体,即大括号里的内容。
1 | protocal Cat { |
协议初始化器要求的类实现
在遵循协议的类中实现的构造器,可以指定为类的指定构造器或便利构造器,在这两种情况下,必须使用 required
修饰构造器。该修饰符保证:所有遵循该协议的子类,都能有一个明确的继承实现。
1 | protocol P { |
将协议作为类型
使用场合:
- 在函数、方法或者初始化器里作为形参类型或者返回类型
- 作为常量、变量或者属性的类型
- 作为数组、字典或者其他存储器的元素的类型
1 | protocol LifeStyle { |
在扩展里添加协议遵循
扩展可以补充协议中已存在的内容,或是提供默认的实现,还可以给协议新增内容。
有条件的遵循协议
1 | extension Array where Element: Equatable { |
使用扩展声明采纳协议
如果一个类型已经遵循类协议的要求,但是还没有声明采纳协议,可以通过一个空的扩展来显式地声明它采纳协议。
1 | struct Hamster { |
协议类型的集合
1 | let things: [TextRepresentable] = [game, d12, simonTheHamster] |
协议继承
1 | protocol InheritingProtocol: SomeProtocol, AnotherProtocol { |
类专用的协议
1 | protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol { |
协议组合
1 | protocol Named { |
协议遵循的检查
- 如果实例遵循协议
is
运算符返回 true 否则返回 false as?
版本的向下转换运算符返回协议的可选项,如果实例不遵循这个协议的话值就是 nilas!
版本的向下转换运算符强制转换协议类型并且在失败是触发运行时错误
可选协议要求
略
协议扩展
略
泛型
类型形式参数
1 | func swapTwoValues<T>(_ a: inout T, _ b: inout T) |
占位符 T 就是类型形式参数,当我们调用函数时,用实际类型来替换类型形参。
## 泛型类型
Swift 允许自定义泛型类型,它们可以使自定义类、结构体、枚举。
1 | struct Stack<Element> { |
扩展一个泛型类型
1 | extension Stack { |
类型约束
类型约束语法
1 | func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { |
类型约束的应用
1 | func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? { |
关联类型
定义一个协议时,声明一个或多个关联类型是很有用的。关联类型个协议中用到的类型一个占位符名称,直到采纳协议时,才指定实际类型。
关联类型的应用
1 | protocol Container { |
给关联类型添加约束
1 | protocol Container { |
在关联类型约束里使用协议
1 | protocol SuffixableContainer: Container { |
扩展现有类型来指定关联类型
Swift 中的 Array 类型已经提供了 Container 协议中的方法和属性,我们只需要用一个空的扩展显示地声明采纳协议即可:
1 | extension Array: Container {} |
现在我们可以把任何 Array 当做一个 Container 使用。
泛型 Where 分句
1 | func allItemsMatch<C1: Container, C2: Container>( |
带有泛型 Where 分句的扩展
1 | extension Container where Item == Double { |
泛型下标
1 | extension Container { |
不透明类型
具有不透明返回类型的函数或者方法会隐藏它返回值的具体类型信息,而以它支持的协议进行描述。隐藏类型信息在模块之间调用代码时很好用,因为返回值的具体类型可以保持私有。不同于返回一个协议类型的值,不透明类型保持了类型的身份——编译器可以访问类型信息,但是模块不能。
不透明类型也可以理解为“反向泛型”,泛型受调用者约束,而不透明类型受被调用者约束。
函数不能返回带有 Self
或 associatedtype
的协议,而不透明类型可以。函数可以返回不同的协议类型,不透明类型每次必须返回相同的类型。
1 | protocol UIMode { |