Swift —— 关键字

整理下 Swift 的一些关键字。主要包括(不定时更新):

  • @inline(__always)  & @inline(never)
  • @discardableResult
  • mutating
  • associatedtype
  • Designated & Convenience & Required

@inline(__always)  & @inline(never)

正如 C 语言中,可以是 inline 声明内联函数,Swift 也可以。只需要给函数表明 @inline(__always) 或者 @inline(never)

1
2
@inline(never) func testInlineNever() { }
@inline(__always) func testInlineAlways() {}

@discardableResult

在 Swift 中,使用一些有返回值的函数。如果没有用参数去承接,那么会有一些警告。一般,我们会用 let _ = 返回值 来消灭这些警告。或者是 使用 @discardableResult 来表明方法,那么就不会有警告了。

1
2
3
4
5
6
7
8
9
func undiscardResult() -> Bool { return true }
@discardableResult
func discardResult() -> Bool { return true }
// 此处会有警告⚠。所以没有标明 discardableResult 的话,可以用 let _ = xxx 来消除警告
let _ = undiscardResult()
// 因为有标明 discardableResult ,所以不会有警告⚠
discardResult()

mutating

struct 和 enum 是值类型。默认情况下,无法在实例方法中进行修改。如果要修改的话,那么需要加上 mutating 进行修饰。这点的话,Xcode 一般会进行提醒。

1
2
3
4
5
6
struct Foo {
var name : String
mutating func change(_ name: String) {
self.name = name
}
}

associatedtype

来自官网的描述:

When defining a protocol, it’s sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name to a type that is used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted. Associated types are specified with the associatedtype keyword.

当定义一个 protocol 的时候,有时候需要制定一些类型,其实就是泛型,用 associatedtype 可以定一个类型。在没有使用前,可以用 associatedtype 关联一些实际的类型。在使用上,当实现该协议的时候,需要使用 typealias 来指定 协议中 associatedtype 所关联的类型。比如 例子中的 Chinese 协议,使用 associatedtype 关联了一个 Person 的虚拟类型。当 Human 实现 Chinese 这个协议,需要使用 typealias 把 Cantonese 指定为 Person,然后对应的方法也会随着变成具体类型。不过使用 associatedtype 后,当继承协议的时候,Xcode 会有提示,需要使用 typealias 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Human { }
struct Cantonese { }
protocol Chinese {
associatedtype Person
func canEatAnything(_ person: Person) -> Bool
}
extension Human : Chinese {
typealias Person = Cantonese
func canEatAnything(_ person: Cantonese) -> Bool {
return true
}
}

Designated & Convenience & Required

Swift 的构造方法要求比较严格。涉及到的关键字主要是 Designated 、 Convenience 、 Required 。

Designated 的意思大概是指定的,顾名思义,其修饰的构造方法是首要的,并且每个类都至少有一个 designated 构造方法,父类的可被子类所继承。

Convenience 的中文含义是便利的。顾名思义,其修饰的构造方法只是便利而已。因此,在优先级上,convenience 修饰的构造方法排第二。而且,在使用上,必须在同一个类内,调用 designated 修饰的构造方法。父类的无法被子类所继承。

两者的关系可以从官方文档的这个关系图看出。

p1

required 修饰的构造方法则是要求子类必须实现父类的这个构造方法。比如说经常用的自定义 UIView,Xcode 则会提示需要实现对应的 required 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Human {
var name : String
var age : Int
init(_ name: String, age: Int) {
self.name = name
self.age = age
}
required init(_ name: String) {
self.name = name
self.age = 0
}
convenience init(_ age: Int) {
self.init("", age: age)
}
}
class Chinese : Human {
// 父类的 designated 构造方法,子类可以进行重载
override init(_ name: String, age: Int) {
super.init(name, age: age)
}
// 父类标明的 required 构造方法,子类必须实现
required init(_ name: String) {
fatalError("init has not been implemented")
}
// 父类标明的 convenience 构造方法,不被子类所继承
}

参考:官方文档:构造方法

结语

暂时就这些。不定时更新~~。(逃