import (导入声明)
导入声明(import declaration) 让你可以使用在其他文件中声明的内容。导入语句的基本形式是导入整个模块,它由 import
关键字和紧随其后的模块名组成:
import 模块
可以对导入操作提供更细致的控制,如指定一个特殊的子模块或者指定一个模块或子模块中的某个声明。提供了这些限制后,在当前作用域中,只有被导入的符号是可用的,而不是整个模块中的所有声明。
import 导入类型 模块.符号名
import 模块.子模块
let (常量)
常量以关键字 let 来声明,遵循如下格式:
let 常量名称: 类型 = 表达式
var (变量)
变量声明(variable declaration) 可以在程序中引入一个具有命名的变量,它以关键字 var 来声明。
可以在子类中重写继承来的变量属性,使用 override
声明修饰符标记属性的声明即可,详情请参阅 重写。
-
存储型变量和存储型变量属性
常量以关键字 let 来声明,遵循如下格式:
var 变量名称: 类型 = 表达式
-
计算型变量和计算型属性
使用如下形式声明一个计算型变量或计算型属性:
var 变量名称: 类型 {
get {
语句
}
set(setter 名称) {
语句
}
}
-
存储型变量和属性的观察器
可以在声明存储型变量或属性时提供 willSet 和 didSet 观察器。一个包含观察器的存储型变量或属性以如下形式声明:
var 变量名称: 类型 = 表达式 {
willSet(setter 名称) {
语句
}
didSet(setter 名称) {
语句
}
}
- 类型变量属性
要声明一个类型变量属性,用 static
声明修饰符标记该声明。类可以改用 class
声明修饰符标记类的类型计算型属性从而允许子类重写超类的实现。类型属性在 类型属性 章节有详细讨论。
typealias (类型别名)
类型别名(type alias) 声明可以在程序中为一个既有类型声明一个别名。类型别名声明语句使用关键字 typealias 声明,遵循如下的形式:
typealias 类型别名 = 现存类型
func (函数声明)
使用函数声明(function declaration) 在程序中引入新的函数或者方法。在类、结构体、枚举,或者协议中声明的函数会作为方法。函数声明使用关键字 func,遵循如下的形式:
func 函数名称(参数列表) -> 返回类型 {
语句
}
如果函数返回 Void 类型,返回类型可以省略,如下所示:
func 函数名称(参数列表) {
语句
}
inout (输入输出参数)
输入输出参数被传递时遵循如下规则:
函数调用时,参数的值被拷贝。
函数体内部,拷贝后的值被修改。
函数返回后,拷贝后的值被赋值给原参数。
这种行为被称为拷入拷出(copy-in copy-out) 或值结果调用(call by value result)。
_ (单参数省略声明)
以下划线(_)命名的参数会被显式忽略,无法在函数内使用。
... (可变参数省略声明)
一个参数的基本类型名称如果紧跟着三个点(...),会被视为可变参数。
mutating (自身修改)
枚举或结构体的方法如果会修改 self,则必须以 mutating
声明修饰符标记。
override (重写超类中的方法)
子类重写超类中的方法必须以 override
声明修饰符标记。重写方法时不使用 override
修饰符,或者被 override
修饰符修饰的方法并未对超类方法构成重写,都会导致编译错误。
static (类型方法)
枚举或者结构体中的类型方法,要以 static
声明修饰符标记,而对于类中的类型方法,除了使用 static
,还可使用 class
声明修饰符标记。类中使用 class
声明修饰的方法可以被子类实现重写;类中使用 class final
或 static
声明修饰的方法不可被重写。
throws (抛出错误的函数和方法)
可以抛出错误的函数或方法必须使用 throws 关键字标记。这类函数和方法被称为抛出函数和抛出方法。它们有着下面的形式:
func 函数名称(参数列表) throws -> 返回类型 {
语句
}
抛出函数或抛出方法的调用必须包裹在 try 或者 try! 表达式中(也就是说,在作用域内使用 try 或者 try! 运算符)。
rethrows (重抛错误的函数和方法)
函数或方法可以使用 rethrows 关键字来声明,从而表明仅当该函数或方法的一个函数类型的参数抛出错误时,该函数或方法才抛出错误。这类函数和方法被称为重抛函数和重抛方法。重新抛出错误的函数或方法必须至少有一个参数的类型为抛出函数。
func someFunction(callback: () throws -> Void) rethrows {
try callback()
}
重抛函数或者方法不能够从自身直接抛出任何错误,这意味着它不能够包含 throw 语句。它只能够传递作为参数的抛出函数所抛出的错误。例如,在 do-catch 语句中调用抛出函数,并在 catch 子句中抛出其它错误都是不允许的。
async (异步函数和方法)
异步运行的函数和方法必须用 async 关键字标记。这些函数和方法称为异步函数和异步方法。它们有着下面的形式:
func 函数名称(参数列表) async -> 返回类型 {
语句
}
对异步函数或异步方法的调用必须包含在 await 表达式中,即它们必须在 await 操作符的作用域内。
async 关键字是函数类型中的一部分。同步函数是异步函数的子类型。所以,你可以在使用异步函数的地方,使用同步函数。同步方法可以重写异步方法,且同步方法可以满足对异步方法的协议要求。
Never (永不返回的函数)
Swift 定义了 Never
类型,它表示函数或者方法不会返回给它的调用者。Never
返回类型的函数或方法可以称为不归,不归函数、方法要么引发不可恢复的错误,要么永远不停地运作,这会使调用后本应执行得代码就不再执行了。但即使是不归函数、方法,抛错函数和重抛出函数也可以将程序控制转移到合适的 catch
代码块。
不归函数、方法可以在 guard 语句的 else 字句中调用。
你可以重写一个不归方法,但是新的方法必须保持原有的返回类型和没有返回的行为。
enum (枚举声明)
枚举声明有两种基本形式,使用关键字 enum 来声明。枚举声明体包含零个或多个值,称为枚举用例,还可包含任意数量的声明,包括计算型属性、实例方法、类型方法、构造器、类型别名,甚至其他枚举、结构体、类和 actor。枚举声明不能包含析构器或者协议声明。
枚举类型可以采纳任意数量的协议,但是枚举不能从类、结构体和其他枚举继承。
不同于类或者结构体,枚举类型并不隐式提供默认构造器,所有构造器必须显式声明。一个构造器可以委托给枚举中的其他构造器,但是构造过程仅当构造器将一个枚举用例赋值给 self 后才算完成。
struct (结构体声明)
使用结构体声明(structure declaration) 可以在程序中引入一个结构体类型。结构体声明使用 struct 关键字,遵循如下的形式:
struct 结构体名称: 采纳的协议 {
多条声明
}
结构体内可包含零个或多个声明。这些声明可以包括存储型和计算型属性、类型属性、实例方法、类型方法、构造器、下标、类型别名,甚至其他结构体、类、actor 和枚举声明。结构体声明不能包含析构器或者协议声明。
class (类声明)
可以在程序中使用类声明(class declaration) 来引入一个类。类声明使用关键字 class,遵循如下的形式:
class 类名: 超类, 采纳的协议 {
多条声明
}
类内可以包含零个或多个声明。这些声明可以包括存储型和计算型属性、实例方法、类型方法、构造器、唯一的析构器、下标、类型别名,甚至其他类、结构体、actor 和枚举声明。类声明不能包含协议声明。
actor (Actor 声明)
可以在程序中使用 actor 声明(actor declaration) 来引入一个 actor。Actor 声明使用关键字 actor,遵循如下的形式:
actor 名称: 遵循的协议 {
多条声明
}
Actor 内可包含零个或多个声明。这些声明包括存储属性和计算属性、实例方法、类型方法、构造器、唯一的析构器、下标、类型别名,甚至其他类、结构体和枚举声明。
protocol (协议声明)
协议声明(protocol declaration) 可以为程序引入一个命名的协议类型。协议声明只能在全局区域使用 protocol 关键字来进行声明,并遵循如下形式:
protocol 协议名称: 继承的协议 {
协议成员声明
}
协议的主体包含零个或多个协议成员声明,这些成员描述了任何采纳该协议的类型必须满足的一致性要求。一个协议可以声明采纳者必须实现的某些属性、方法、构造器以及下标。协议也可以声明各种各样的类型别名,叫做关联类型,它可以指定协议的不同声明之间的关系。协议声明不能包括类、结构体、枚举或者其它协议的声明。
associatedtype (协议关联类型声明)
使用关键字 associatedtype 来声明协议关联类型。关联类型为作为协议声明的一部分,为某种类型提供了一个别名。关联类型和泛型参数子句中的类型参数很相似,但是它们和 Self 一样,用于协议中。Self 指代采纳协议的类型。
subscript (下标声明)
下标声明(subscript declaration) 用于为特定类型的对象添加下标支持,通常也用于为访问集合、列表和序列中的元素提供语法便利。下标声明使用关键字 subscript,形式如下:
subscript (参数列表) -> 返回类型 {
get {
语句
}
set(setter 名称) {
语句
}
}
下标声明只能出现在类、结构体、枚举、扩展和协议的声明中。
init (构造器声明)
构造器声明会为程序中的类、结构体或枚举引入构造器。构造器使用关键字 init 来声明,有两种基本形式。
结构体、枚举、类可以有任意数量的构造器,但是类的构造器具有不同的规则和行为。不同于结构体和枚举,类有两种构造器,即指定构造器和便利构造器.
convenience (便利构造器)
便利构造器可以将构造过程委托给另一个便利构造器或一个指定构造器。但是,类的构造过程必须以一个将类中所有属性完全初始化的指定构造器的调用作为结束。便利构造器不能调用超类的构造器。
required (子类必须实现)
可以使用 required 声明修饰符,将便利构造器和指定构造器标记为每个子类都必须实现的构造器。这种构造器的子类实现也必须使用 required 声明修饰符标记。
默认情况下,超类中的构造器不会被子类继承。但是,如果子类的所有存储型属性都有默认值,而且子类自身没有定义任何构造器,它将继承超类的构造器。如果子类重写了超类的所有指定构造器,子类将继承超类的所有便利构造器。
和方法、属性和下标一样,需要使用 override 声明修饰符标记重写的指定构造器。
注意
如果使用 required 声明修饰符标记一个构造器,在子类中重写这种构造器时,无需使用 override 修饰符。
就像函数和方法,构造器也可以抛出或者重抛错误,你可以在构造器参数列表的圆括号之后使用 throws 或 rethrows 关键字来表明相应的抛出行为。
init? (可失败构造器)
可失败构造器可以生成所属类型的可选实例或者隐式解包可选实例,因此,这种构造器通过返回 nil 来指明构造过程失败。
声明生成可选实例的可失败构造器时,在构造器声明的 init 关键字后加追加一个问号(init?)。声明生成隐式解包可选实例的可失败构造器时,在构造器声明后追加一个叹号(init!)。
deinit (析构器声明)
析构器声明(deinitializer declaration) 可以为类声明一个析构器。析构器没有参数,遵循如下格式:
deinit {
语句
}
当没有任何强引用引用着类的对象,对象即将被释放时,析构器会被自动调用。析构器只能在类主体的声明中声明,不能在类的扩展声明中声明,并且每个类最多只能有一个析构器。
子类会继承超类的析构器,并会在子类对象将要被释放时隐式调用。继承链上的所有析构器全部调用完毕后子类对象才会被释放。
析构器不能直接调用。
extension (扩展声明)
扩展声明(extension declaration) 可以扩展一个现存的类型的行为。
扩展声明使用关键字 extension,遵循如下格式:
extension 类型名称 where 要求 {
声明语句
}
扩展声明可以为一个现有的类、结构体或者枚举类型添加协议遵循:
extension 类型名称: 采纳的协议 where 约束条件 {
多条声明
}
operator (运算符声明)
运算符声明(operator declaration) 会向程序中引入中缀、前缀或后缀运算符,使用关键字 operator
来声明。
可以声明三种不同的缀性:中缀、前缀和后缀。运算符的缀性指定了运算符与其运算对象的相对位置。
运算符声明有三种基本形式,每种缀性各一种。运算符的缀性通过在 operator
关键字之前添加声明修饰符 infix
,prefix
或 postfix
来指定。每种形式中,运算符的名字只能包含 运算符 中定义的运算符字符。
- 下面的形式声明了一个新的中缀运算符:
infix operator 运算符名称: 优先级组
中缀运算符是二元运算符,置于两个运算对象之间,例如加法运算符(+
)位于表达式 1 + 2
的中间。
中缀运算符可以选择指定优先级组。如果没有为运算符设置优先级组,Swift 会设置默认优先级组 DefaultPrecedence
,它的优先级比三目优先级 TernaryPrecedence
要高,更多内容参考优先级组声明
- 下面的形式声明了一个新的前缀运算符:
prefix operator 运算符名称
出现在运算对象前边的前缀运算符是一元运算符,例如表达式 !a
中的前缀非运算符(!
)。
前缀运算符的声明中不指定优先级,而且前缀运算符是非结合的。
- 下面的形式声明了一个新的后缀运算符:
postfix operator 运算符名称
紧跟在运算对象后边的后缀运算符是一元运算符,例如表达式 a!
中的后缀强制解包运算符(!
)。
和前缀运算符一样,后缀运算符的声明中不指定优先级,而且后缀运算符是非结合的。
声明了一个新的运算符以后,需要实现一个跟这个运算符同名的函数来实现这个运算符。如果是实现一个前缀或者后缀运算符,也必须使用相符的 prefix 或者 postfix 声明修饰符标记函数声明。如果是实现中缀运算符,则不需要使用 infix 声明修饰符标记函数声明。
优先级组声明
优先级组声明(A precedence group declaration) 会向程序的中缀运算符引入一个全新的优先级组。当没有用圆括号分组时,运算符优先级反应了运算符与它的操作数的关系的紧密程度。 优先级组的声明如下所示:
precedencegroup 优先级组名称{
higherThan: 较低优先级组的名称
lowerThan: 较高优先级组的名称
associativity: 结合性
assignment: 赋值性
}
较低优先级组和较高优先级组的名称说明了新建的优先级组是依赖于现存的优先级组的。
声明修饰符
声明修饰符都是关键字或上下文相关的关键字,可以修改一个声明的行为或者含义。可以在声明的特性(如果存在)和引入该声明的关键字之间,利用声明修饰符的关键字或上下文相关的关键字指定一个声明修饰符。
class
该修饰符用于修饰任何类成员,表明是类自身的成员,而不是类实例的成员。父类中使用该修饰符标记或者未被 final
修饰符标记的成员,都允许被子类重写。
dynamic
该修饰符用于修饰任何兼容 Objective-C 的类的成员。访问被 dynamic
修饰符标记的类成员将总是由 Objective-C 运行时系统进行动态派发,而不会由编译器进行内联或消虚拟化。
因为被标记 dynamic
修饰符的类成员会由 Objective-C 运行时系统进行动态派发,所以它们会被隐式标记 objc
特性。
final
该修饰符用于修饰类或类中的属性、方法以及下标。如果用它修饰一个类,那么这个类不能被继承。如果用它修饰类中的属性、方法或下标,那么它们不能在子类中被重写。
lazy
该修饰符用于修饰类或结构体中的存储型变量属性,表示该属性的初始值最多只被计算和存储一次,且发生在它被第一次访问时。关于如何使用 lazy
修饰符的例子,请参阅 惰性存储型属性。
optional
该修饰符用于修饰协议中的属性、方法以及下标成员,表示符合类型可以不实现这些成员要求。
只能将 optional
修饰符用于被 objc
特性标记的协议。这样一来,就只有类类型可以采纳并符合拥有可选成员要求的协议。关于如何使用 optional
修饰符,以及如何访问可选协议成员(比如,不确定符合类型是否已经实现了这些可选成员)的信息,请参阅 可选协议要求。
required
该修饰符用于修饰类的指定构造器或便利构造器,表示该类所有的子类都必须实现该构造器。在子类实现该构造器时,必须同样使用 required
修饰符修饰该构造器。
static
该修饰符用于修饰结构体、类、枚举或协议的成员,表明是类型成员,而不是类型实例的成员。在类声明的作用范围内,使用 static
修饰符标记成员声明语句,同 class
和 final
修饰符具有相同的效果。但是类的常量类型属性是一个例外: static
没有问题,但是你无法为常量声明使用 class
或 final
修饰符。
unowned
该修饰符用于修饰存储型变量、常量或者存储型变量属性,表示该变量或属性持有其存储对象的无主引用。如果在此存储对象释放后尝试访问该对象,会引发运行时错误。如同弱引用一样,该引用类型的变量或属性必须是类类型。与弱引用不同的是,这种类型的变量或属性是非可选的。关于 unowned
更多的信息和例子,请参阅 无主引用
unowned(safe)
unowned
的显式写法
unowned(unsafe)
该修饰符用于修饰存储型变量、常量或者存储型变量属性,表示该变量或属性持有其存储对象的无主引用。如果在此存储对象释放后尝试访问该对象,会直接访问该对象释放前存储的内存地址,因此这是非内存安全的操作。如同弱引用一样,该引用类型的变量或属性必须是类类型。与弱引用不同的是,这种类型的变量或属性是非可选的。关于 unowned
更多的信息和例子,请参阅 无主引用。
weak
该修饰符用于修饰变量或存储型变量属性,表示该变量或属性持有其存储的对象的弱引用。这种变量或属性的类型必须是可选的类类型。使用 weak
修饰符可避免强引用循环。关于 weak
修饰符的更多信息和例子,请参阅 弱引用。
访问控制级别
Swift 提供了五个级别的访问控制:open
、public
、internal
、file private
和 private
。可以使用以下任意一种访问级别修饰符来指定声明的访问级别。访问控制在 访问控制 中有详细讨论。
open
该修饰符表示声明可被同模块的代码访问,且可作为基类使用,只要其他模块导入了声明所在的模块,也可以进行访问,且可作为基类使用。
public
该修饰符表示声明可被同模块的代码访问,且可作为基类使用,只要其他模块导入了声明所在的模块,也可以进行访问,但不可作为基类使用。
internal
该修饰符表示声明只能被同模块的代码访问。默认情况下,绝大多数声明会被隐式标记 internal
访问级别修饰符。
fileprivate
该修饰符表示声明只能被所在源文件的代码访问。
private
该修饰符表示声明只能被声明所直接包含的作用域内的代码访问。
为了达到访问控制的目的,同一文件中相同类型的扩展共享访问控制作用域。如果这些扩展与它们扩展的类型也在同一个文件中,则这些扩展共享该类型的访问控制作用域。在类型声明中声明的私有成员可以从扩展中访问,在某个扩展中声明的私有成员可以从其他扩展和类型声明中访问。
dynamicMemberLookup
该特性用于类、结构体、枚举或协议,让其能在运行时查找成员。该类型必须实现 subscript(dynamicMember:) 下标。
discardableResult
该特性用于的函数或方法声明,以抑制编译器中函数或方法被调用而其返回值没有被使用时的警告。
dynamicCallable
该特性用于类、结构体、枚举或协议,以将该类型的实例视为可调用的函数。该类型必须实现 dynamicallyCall(withArguments:)、dynamicallyCall(withKeywordArguments:) 方法之一,或两者同时实现。
inlinable
该特性用于函数、方法、计算属性、下标、便利构造器或析构器的声明,以将该声明的实现公开为模块公开接口的一部分。编译器允许在调用处把 inlinable 标记的符号替换为符号实现的副本。
main
将该特性用于结构体、类,或枚举的声明,表示它包含了程序流的顶级入口。类型必须提供一个不接收任何参数,且返回值为 Void 的 main 类型函数。
nonobjc
针对方法、属性、下标、或构造器的声明使用该特性将覆盖隐式的 objc 特性。nonobjc 特性告诉编译器该声明不能在 Objective-C 代码中使用,即便它能在 Objective-C 中表示。
NSApplicationMain
在类上使用该特性表示该类是应用程序委托类。使用该特性与调用 NSApplicationMain(::) 函数的效果相同。
NSCopying
该特性用于修饰一个类的存储型变量属性。该特性将使属性的设值方法使用传入值的副本进行赋值,这个值由传入值的 copyWithZone(_:) 方法返回,而不是传入值本身。该属性的类型必需符合 NSCopying 协议。
NSCopying 特性的行为与 Objective-C 中的 copy 属性特性相似。
NSManaged
该特性用于修饰 NSManagedObject 子类中的实例方法或存储型变量属性,表明它们的实现由 Core Data 在运行时基于相关实体描述动态提供。对于标记了 NSManaged 特性的属性,Core Data 也会在运行时为其提供存储。应用这个特性也意味着 objc 特性。
objc
该特性用于修饰任何可以在 Objective-C 中表示的声明。比如,非嵌套类、协议、非泛型枚举(仅限原始值为整型的枚举)、类的属性和方法(包括存取方法)、协议以及协议中的可选成员、构造器以及下标运算符。objc 特性告诉编译器这个声明可以在 Objective-C 代码中使用。
该特性用在扩展中,与在没有明确标记为 nonobjc 特性的扩展中给每个成员添加该特性具有相同效果。
objcMembers
该特性用于类声明,以将 objc 特性应用于该类、扩展、子类以及子类的扩展的所有 Objective-C 兼容成员。
大多数代码应该使用 objc 特性,以暴露所需的声明。如果需要暴露多个声明,可以将其分组到添加 objc 特性的扩展中。objcMembers 特性为大量使用 Objective-C 运行时的内省工具的库提供了便利。添加不必要的 objc 特性会增加二进制体积并影响性能。
propertyWrapper
在类、结构体或者枚举的声明时使用该特性,可以让其成为一个属性包装器。如果将该特性应用在一个类型上,将会创建一个与该类型同名的自定义特性。将这个新的特性用于类、结构体、枚举的属性,则可以通过包装器的实例封装对该属性的访问;本地存储变量声明也能利用这个特性完成对它的访问封装。局部和全局变量不能使用属性包装器。
resultBuilder
将该特性应用于类、结构体或者枚举,可以把它作为结果构造器使用。结果构造器能按顺序构造一组嵌套的数据结构。利用它,可以以一种自然的声明式语法为嵌套数据结构实现一套领域专门语言(DSL)。
requires_stored_property_inits
该特性用于类声明,以要求类中所有存储属性提供默认值作为其定义的一部分。对于从中继承的任何类都推断出 NSManagedObject 特性。
testable
将此特性应用于 import 声明以导入该模块,并更改其访问控制以简化对该模块代码的测试。这样就能访问被导入模块中的任何标有 internal 访问级别修饰符的实体,犹如它们被标记了 public 访问级别修饰符。测试也可以访问使用 internal 或者 public 访问级别修饰符标记的类和类成员,就像它们是 open 访问修饰符声明的。被导入的模块必须以允许测试的方式编译。
UIApplicationMain
在类上使用该特性表示该类是应用程序委托类。使用该特性与调用 UIApplicationMain 函数并且把该类的名字作为委托类的名字传递给函数的效果相同。
如果你不想使用这个特性,可以提供一个 main.swift 文件,并在代码顶层调用 UIApplicationMain(::::) 函数。比如,如果你的应用程序使用一个继承于 UIApplication 的自定义子类作为主要类,你可以调用 UIApplicationMain(::::) 函数而不是使用该特性。
usableFromInline
该特性用于函数、方法、计算属性、下标、构造器或析构器的声明,以在同一模块中允许该符号用于内联代码的声明。声明必须具有 internal 访问级别修饰符。被标记为 usableFromInline 的结构体或类它们属性的类型只能是被标记为 public 或者 usableFromInline 的类型。被标记为 usableFromInline 的枚举,它 case 的真实值或者关联类型只能是被标记为 public 或者 usableFromInline 的类型。
warn-unqualified-access
该特性应用于顶级函数、实例方法、类方法或静态方法,以在没有前置限定符(例如模块名称、类型名称、实例变量或常量)的情况下使用该函数或方法时触发警告。使用该特性可以减少在同一作用域里访问的同名函数之间的歧义。
Interface Builder 使用的声明特性
Interface Builder 特性是 Interface Builder 用来与 Xcode 同步的声明特性。Swift 提供了以下的 Interface Builder 特性:IBAction,IBSegueAction,IBOutlet,IBDesignable,以及 IBInspectable。这些特性与 Objective-C 中对应的特性在概念上是相同的。
IBOutlet 和 IBInspectable 用于修饰一个类的属性声明。IBAction 和 IBSegueAction 特性用于修饰一个类的方法声明,IBDesignable 用于修饰类的声明。
应用 IBAction、IBSegueAction、IBOutlet、IBDesignable 或者 IBInspectable 特性都意味着同时应用 objc 特性。
autoclosure
这个特性通过把表达式自动封装成无参数的闭包来延迟表达式的计算。它可以修饰类型为返回表达式结果类型的无参数函数类型的函数参数。
convention
该特性用于修饰函数类型,它指出了函数调用的约定。
convention 特性总是与下面的参数之一一起出现。
swift 参数用于表示一个 Swift 函数引用。这是 Swift 中函数值的标准调用约定。
block 参数用于表示一个 Objective-C 兼容的块引用。函数值会作为一个块对象的引用,块是一种 id 兼容的 Objective-C 对象,其中嵌入了调用函数。调用函数使用 C 的调用约定。
c 参数用于表示一个 C 函数引用。函数值没有上下文,不具备捕获功能,并且使用 C 的调用约定。
除了少数例外,当函数需要任何其他调用约定时,可以转换成任意调用约定的函数。非范型全局函数、不捕获任何局部变量的局部函数或不捕获任何局部变量的闭包可以转换为 C 调用约定。其余的 Swift 函数不能转换成 C 调用约定。一个 Objective-C 块调用约定的函数不能转换成 C 调用约定。
escaping
在函数或者方法声明上使用该特性,它表示参数将不会被存储以供延迟执行。这将确保参数不会超出函数调用的生命周期。在使用 escaping
特性声明的函数类型中访问属性和方法时需要显式地使用 self.
。
unknown
该特性用于 switch case,用于没有匹配上代码编译时已知 case 的情况。有关如何使用 unknown
特性的示例,可参阅 对未来枚举的 case
进行 switch
。