基础部分
常量和变量
声明常量和变量
常量和变量必须在使用前声明,用let
声明常量,用var
声明变量。
let a = 10
var b = 0
类型标注
var message: String
常量和变量的命名
let π = 3.141592654
let 你好 = "你好,世界。"
let ☏ = "110"
下面的例子中,friendlyWelcome
由Hello!
变为Hi
。
var friendlyWelcome = "Hello!"
friendlyWelcome = "Hi"
但是下面这段代码,在编译时会报错。
let languageName = "swift"
languageName = "Objective-C"
// 因为languageName是常量,其值不可改变。
输出常量和变量
println(friendlyWelcome)
// 输出“Hi”
println("this is a string")
// 输出“this is a string”
下面这段代码会告诉你字符串插值怎么使用。
println("The current value of friendlyWelcome is \(friendlyWelcome)")
// 输出“The current value of friendlyWelcome is Hi”
注释
//这是一个单行注释
/* 这是一个 多行注释。 */
分号
如果你打算在同一行写多条独立的语句,那么分号是必须的,否则,分号不是必须的。
整数
整数范围
let maxValue = UInt8.max // 255
let minValue = UInt8.min // 0
Int
在32位平台上,Int
和Int32
长度相同。
在64位平台上,Int
和Int64
长度相同。
UInt
一般情况下不推荐使用UInt。
浮点数
Double表示64位浮点数,当你需要存储很大或者很高精度的浮点数时请使用此类型。
Float表示32位浮点数。精度要求不高的话可以使用此类型。
类型安全和类型推断
Swift是类型安全的,它在编译时进行类型检查,把不匹配的类型标记为错误,可以让你再开发的时候尽早发现并修复错误。
let meaningOfLife = 42
// meaningOfLife会被推测为Int类型
如果你没有给浮点字面量标明类型,Swift会推断你想要的是Double
:
let pi = 3.14159
// pi会被推测为Double类型
当推断浮点数的类型时,Swift总是会选择Double
而不是Float
。
如果表达式中同时出现了整数和浮点数,会被推断为Double
类型。
let anotherPi = 3 + 0.14159
// anotherPi 会被推测为Double类型
数值型字面量
整数字面量可以被写作:
- 一个十进制数,没有前缀
- 一个二进制数,前缀是
0b
- 一个八进制数,前缀是
0o
- 一个十六进制数,前缀是
0x
下面的所有整数字面量的十进制都是17:
let decimalInteger = 17
let binaryInteger = 0b10001
let octalInteger = 0o21
let hexadecimalInteger = 0x11
浮点字面量还有一个可选的指数,在十进制浮点数中通过大写或者小写的e
来指定,在十六进制浮点数中通过大写或者小写的p
来指定。
如果一个十进制数的指数为exp
,那么这个数相当于基数和10^exp的乘积:
1.25e2
表示1.25 * 10^2,等于125.0
。1.25e-2
表示1.25 * 10^-2,等于0.0125
。
如果一个十六进制的指数为exp
,那么这个数相当于基数和2^exp的乘积:0xFp2
表示15 * 2^2,等于60.0
。0xFp-2
表示15 * 2^-2,等于3.75
。
下面这些浮点字面量都等于十进制的12.1875
。
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
数值型类型转换
整数转换
let cannotBeNegative: UInt8 = -1
// UInt8类型不能存储负数,所以会报错
let tooBig: Int8 = Int8.max + 1
// Int8类型不能存储超过最大值的数,所以会报错
整数和浮点数转换
let three = 3
let point = 0.14159
let pi = Double(three) + point
// pi等于3.14159,所以被推测为Double类型
类型别名
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound现在是0
布尔值
let orangs = true
let turn = false
当你在编写条件语句比如if
语句的时候,布尔值非常有用。
if turn {
println("ok");
} else {
println("no");
}
元组
元组把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。
let http404Error = (404,"Not Found")
// http404Error的类型是(Int,String),值是(404,"Not Found")
可以将一个元组的内容分解成单独的常量和变量,然后就可以正常使用它们了:
let (statusCode,statusMessage) = http404Error
println("The status code is \(statusCode)")
// 输出 "The status code is 404"
println("The status message is \(statusMessage)")
// 输出 "The status message is Not Found"
如果只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_
)标记:
let (justTheStatusCode,_) = http404Error
println("The status code is \(justTheStatusCode)")
// 输出 "The status code is 404"
此外,还可以通过下标来访问元组中的单个元素,下标从零开始:
println("The status code is \(http404Error.0)")
// 输出 "The status code is 404"
println("The status message is \(http404Error.1)")
// 输出 "The status message is Not Found"
可以在定义元组的时候给单个元素命名:
let http200Status = (statusCode: 200,description: "OK")
给元组中的元素命名后,可以通过名字来获取这些元素的值:
println("The status code is \(http200Status.statusCode)")
// 输出 "The status code is 200"
println("The status message is \(http200Status.description)")
// 输出 "The status message is OK"
可选类型
举一个例子,Swift的String
类型有一个叫toInt
的方法,作用是将一个String
值转换为一个Int
值,然而不是所有的字符串都可以转换为整数。字符串"123"
可以被转换为数字123
,但是字符串"Hello,World"
不行。
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
// convertedNumber被推测为类型"Int?"
使用可选类型来处理值可能缺失的情况。一个可选的Int
被写作Int?
而不是Int
。问号暗示包含的值是可选类型,也就是说可能包含Int
值也可能不包含值。
可以使用if
语句来判断一个可选是否包含值。如果可选类型有值,结果是true
,如果没有值,结果是false
。
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个(!
)来获取值。这个惊叹号表示我知道这个可选有值,请使用它,这被称为可选值得强制解析。
if convertedNumber != nil {
println("\(possibleNumber) has an integer value of \(convertedNumber)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
// 输出 "123 has an integer value of 123"
可选绑定
使用可选绑定来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if
和while
语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。
if let actualNumber = possibleNumber.toInt() {
println("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
// 输出 "123 has an integer value of 123"
nil
可以给可选变量赋值为nil
来表示它没有值:
var serverResponseCode: Int? = 404
// serverResponseCode包含一个可选的Int值404
serverResponseCode = nil
// serverResponseCode现在不包含值
nil
不能用于非可选的常量和变量。如果你的代码中有常量或变量需要处理值缺失的情况,请把它们声明成对应的可选类型
如果你声明一个可选常量或变量但是没有赋值,它们会自动被设置为nil
:
var surveyAnswer: String?
// surveyAnswer被自动设置为nil
Swift的nil
和Objective-C中的nil
并不一样。在Objective-C中,nil
是一个指向不存在对象的指针。在Swift中,nil
不是指针,它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为nil
,不只是对象类型。
隐式解析可选类型
有时候在程序架构中,第一次被赋值之后,可以确定一个可选类型总会有值。在这种情况下,每次判断和解析可选值是非常低效的,因为可以确定它总是会有值。
这种类型的可选状态被定义为隐式解析可选类型,把想要用作可选的类型的后面的问号改成惊叹号来声明一个隐式解析可选类型。
let possibleString: String? = "An optional string."
println(possibleString!) //需要惊叹号来获取值
// 输出 "An optional string."
let assumedString: String! = "An implicitly unwrapped optional string."
println(assumedString) //不需要惊叹号
// 输出 "An implicitly unwrapped optional string."
你仍然可以把隐式解析可选类型当做普通可选类型来检查并解析它的值:
if assumedString {
println(assumedString)
}
// 输出 "An implicitly unwrapped optional string."
你也可以在可选绑定中使用隐式解析可选类型来检查并解析它的值:
if let definiteString = assumedString {
println(definiteString)
}
// 输出 "An implicitly unwrapped optional string."
断言
使用断言进行调试
let age = -3
assert(age >= 0,"A person's age cannot be less than zero")
// 因为 age < 0, 所以断言会触发
断言信息如果不需要,可以被省略:
assert(age >= 0)
何时使用断言
当条件可能为假时使用断言,但是最终一定要保证条件为真,这样你的代码才能继续运行。断言的适用情景: