跳到主要内容

基础语法

常量 & 变量

定义常量 & 变量

let PI = 3.14159
var x = 1, y = 2, z = 3

如果给赋值过的常量赋值,会在代码编译时报错。

类型标注

可以对常量或变量进行类型标注:

var welcomeMessage: String

一般很少会用到类型标注。如果你给定了常量或变量的初始值,Swift 会自己推断其类型。

常量变量的命名

可以用任何字符命名,包括 Unicode 字符:

let 你好 = "你好世界"
let 🐶🐮 = "dogcow"

但是名字不能:

  • 包含空白字符、数学符号、箭头、私用 Unicode 字符等字符;

  • 以数字开头;

  • 为已定义的常量变量名,或 Swift 的关键字;

如果迫不得已想使用 Swift 的关键字作为名字,请用 ` 包裹名字。

打印常量变量

使用 print(_:separator:terminator:) 打印一个值:

let hello = "hello world!"

print(hello)

注释

可以用 ///* ... */ 进行注释,后者支持嵌套:

// 这是一行注释.

/* 这是外层注释的开头
/* 打印 hello */
print(hello)
这是外层注释的结尾 */

分号

Swift 并不要求你在每条语句后面加上分号,除非你在一行里写了多个语句:

let cat = "🐱"; print(cat)

整数

Swift 提供有符号或无符号的 8、16、32、64 位整数。类型名与 C 语言中的类似,比如 8 位无符号为 UInt8 。

Swift 中所有类型名都是首字母大写的。

整数范围

可以访问整数类型名的 minmax 属性获取其最大最小值:

let minValue = UInt8.min  // => 0
let maxValue = UInt8.max // => 255

Int & UInt

在 Swift 中,你可以直接用 Int 或 UInt 作为整数类型:

  • 对于 32 位的系统 Int 和 Int32 一样大小,UInt 同理;

  • 对于 64 位的系统,Int 和 Int64 一样大小,UInt 同理。

大部分场景还是 Int 用的多一点,除非确实是想使用无符号类型。

浮点数

Swift 中的两种浮点数类型:

  • Double 为 64 位浮点数类型(能保证的精度为 15 位);

  • Float 为 32 位浮点数类型(能保证的精度为 6 位)。

类型安全 & 类型推断

Swift 会在编译阶段对代码进行类型检查。同时,对于未明确类型的值,Swift 会进行类型推断:

// Swift 会将整数推断为 Int 类型
var age = 22

// Swift 会将浮点数推断为 Double 类型
let PI = 3.14159

数值字面量

  • 二、八、十六进制的前缀分别为 0b0o0x

  • 十进制浮点数可以用 e or E 带上指数,十六进制则用 p or P

  • 可以有多余的前缀 0 ;

  • 可以用 _ 来按位数分隔,提高数值的可读性;

let a = 10          // => 10
let b = 0b10001 // => 17
let c = 1.25e-2 // => 0.0125
let d = 000123.45 // => 123.45
let e = 1_000_000 // => 1000000

数值类型的转换

// 范围外的数会直接报错
let a: UInt8 = -1 // ERROR

// 计算中发生的溢出也会直接报错
let b: Int8 = Int8.max + 1 // ERROR
let c = Int16(Int8.max) + 1 // 128

// 浮点数转为整数会直接截断,而不是四舍五入
let d = Int(3.14159) // 3

类型别名

可以用 typealias 关键字来给一个类型取别名:

typealias AudioSample = UInt16

布尔值

Swift 的布尔值类型名为 Bool ,值可为 true or false

元组 Tuple

可以用元组直接将多个值包裹成一个值:

// 类型为 (Int, String)
let http404Error = (404, "Not Found")

同时可以用类似元组的语法来分解一个元组值:

let (statusCode, statusMessage) = http404Error

// 如果想忽略一个值,用下划线 _ 代替
let (justTheStatusCode, _) = http404Error

可以用索引属性访问元组值里的元素:

http404Error.0  // => 404
http404Error.1 // => "Not Found"

元组支持对元素进行命名,元素名将对应地成为属性名:

let http200Status = (statusCode: 200, description: "OK")
http404Error.statusCode // => 404
http404Error.description // => "Not Found"

在函数中,可以直接使用元组来返回多个值。但对于数据结构较为复杂的,应当使用结构体或类。

可选值 Optional

可以在类型名后面加个问号 ? ,表示该类型可能为空,即 nil

// 一个可选的 Int 类型
var serverResponseCode: Int? = 404
serverResponseCode = nil

// 如果没有给定初值,则初值会自动为 nil
var surveyAnswer: String? // => nil

不能给非可选类型的常量变量赋值为 nil

强制非空

如果确定一个可选值不为空,可以用 ! 来告诉 Swift :

if optionalNum != nil {
print("optionalNum has an integer value of \(optionalNum!).")
}

对一个空值使用 ! 会触发运行时错误。

可选值绑定

可以通过 let 搭配控制语句,来提取可选值中的值:

if let num = optionalNum {
// 如果 optionalNum 不为空,则进入该分支,且 num 为其值
} else {
// 如果 optionalNum 为空,则进入该分支
}

可以用逗号 , 来列出多个可选值绑定:

while let a = optionalA, b = optionalB, c = optionalC {
// ...
}

隐式的强制非空

在声明一个常量变量时也可以用 ! 来强制其为非空:

let possibleStr: String? = "An optional string."
let forcedStr: String = possibleStr! // 需要 `!`

let assumedStr: String! = "An implicitly unwrapped optional string."
let implicitStr: String = assumedStr // 不需要 `!`

但如果赋值的对象不是一个明确给定类型、且类型非可选,则依然表现为可选值:

let optionalStr = assumedStr  // optionalStr 类型为 `String?`

隐式的强制非空可选值也可以进行可选值绑定。与普通的可选值的区别在于,非空的情况分支里不再需要 ! 来强制非空:

if let definiteStr = assumedStr {
print(definiteStr)
}

错误处理

函数声明时可以用 throws 表明可能会抛出错误:

func canThrowAnError() throws {
// this function may or may not throw an error
}

错误可以用 do-catch 语句捕获:

do {
try canThrowAnError()
// no error was thrown
} catch {
// an error was thrown
}

对不同的错误可以定义相应的处理:

do {
try makeASandwich()
eatASandwich()
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}

断言 & 前置条件

  • 断言( Assertion )一般是用于开发阶段发现错误;

  • 前置条件( Preconditiaon )一般是用于生产阶段检测问题。

两者都是用在运行时的。与错误处理不同,断言 or 前置条件一旦触发则会导致程序终止。

使用断言进行调试

可以用 assert(_:_:file:line:) 进行断言:

let age = -3
assert(age >= 0, "一个人的年龄不可能小于 0 。") // 会导致失败

或者用 assertionFailure(_:file:line:) 直接宣告失败:

if age > 10 {
print("你可能在上中学。")
} else if age >= 0 {
print("你可能在上幼儿园。")
} else {
assertionFailure("一个人的年龄不可能小于 0 。")
}

使用前置条件来强制判断

可以用 precondition(_:_:file:line:) 进行前置条件判断:

// 在一个下标方法中 ...
precondition(index > 0, "索引值必须大于 0 。")

同样可以用 preconditionFailure(_:file:line:) 直接宣告失败。

参考

The Basics - docs.swift.org