注:本文为自己学习The Swift Programming Language的笔记,其中的例子为引用原书和其他博文或自己原创的。每个例子都会批注一些实践过程中的经验或思考总结。
1.基本数据类型
Swift的基本数据类型包括整型[Int]、浮点型[Double]和[Float]、布尔型[Bool]和字符串[String],首字母均为大写,区别于Java中的数据类型类。
Swift还支持两种基本数据集合类型:数组[Array]和字典[Dictionary],用于存放数据的集合。
在以上常用数据类型基础上,Swift还引入了元组[Tuple]和可空类型[Optional]。
如果对Python熟悉,那么元组的概念并不陌生。元组是通常不可变长度的元素集合,它能把包含的元素当作一个整体传值。元组常被作为函数返回值,以元组的形式返回多个值。
可空类型是一个全新的概念,能够反映出Swift语言的类型安全[type safe]的特征。可空类型用基本类型后面跟一个问号表示,它要么有一个值,要么它为空。这样的语法规定可以有效地避免可能会出现的类型错误。可空类型贯穿Swift使用始终,是Swift及其重要的一个语言特征。
2.变量和常量
let声明常量,var声明变量,这在前面的学习中我们已经很熟悉了。对于没有添加数据类型的变量或常量,编译器会根据初始赋值自动识别。虽然编译器会根据类型安全原则推断数据类型,但还是建议在声明变量或常量时附上数据类型,便于程序员自己辨识数据类型定义并且也可能避免出现一些隐蔽的类型错误。: 接数据类型表示它有数据类型XXX。完整的声明如下:
let welcomeMessage : String = "Hello Swift!"
定义变量和常量名时可以使用Unicode字符,我们可以定义中文或表情符号的变量名。但这种命名方式并不常用,可读性扩展性也较差,属于Swift的彩蛋环节。
常量的值一旦给出就不能改变,包括常量类实例的成员也不可变。
常量和变量之间不能相互转化。
3.注释
为代码添加注释是好习惯,增加代码可读性。Swift注释和Objective-C、C语言用法一致:
//单行注释
/*
多行
注释
*/
4.分号
Swift一般省略分号,在单行中完成两个语句一定要用;隔开。
5.整数类型
Swift支持8位、16位、32位和64位的有符号数[Signed Integer]和无符号数[Unsigned Integer],命名规则为:Int前缀U表示无符号数无前缀为有符号数,后缀为位数。例如32位无符号数表示为UInt32。
有些时候程序需要和最大值或最小值进行比较,Swift整型提供该类型的最大值和最小值:
println("The max of Unsigned 8bit Integer is \(UInt8.max)")
//prints The max of Unsigned 8bit Integer is 255
在64位机器上,Int默认为Int64,UInt默认为UInt64。
6.浮点类型
Swift中,[Float]是32位浮点数,小数点精度为6位;[Double]是64位浮点数,小数点精度至少是15位,需要高精度数据时一般使用Double。
let d1 : Double = 1 / 3
let d2 : Float = 1 / 3
println("Double of 1/3 is \(d1), and \(d2) in Float.")
//prints Double of 1/3 is 0.333333333333333, and 0.333333343267441 in Float.
可以看到Double型常量比Float型常量拥有更高的精度。
6.浮点类型
Swift作为一种类型安全的程序设计语言,在编译时会进行类型检查工作,不匹配的类型会被标识为错误。
类型推断,也就是之前说的编译器自动推断变量、常量类型,它遵守类型安全原则。在类型推断中,整型赋值默认推断为Int,而浮点型默认推断为Double
7.数制
Swift支持不同的数制,用前缀表示。
整数的进制表达和其他语言类似:十进制数没有前缀,二进制数前缀为[0b],八进制数前缀为[0o],十六进制数前缀为[0x]
对于浮点数,在Swift中可以有十进制和十六进制浮点数。在小数点的两端必须有值。
浮点数可以用指数形式表达,十进制指数用关键字e声明,二进制指数用关键字p声明(用于十六进制浮点数中)。
例如:1.25e-2 表示 1.25 × 10-2 也就是 0.0125,0xFp-2 表示 15 × 2-2 也就是 3.75。
整数和浮点数可以添加冗余信息来提高可读性,例如:首位添0,数字中添加下划线等。
8.数值类型转换
8.1整数转换
首先整数必须严格遵守其数值界限,-1和256都是不允许存放在UInt8中的。
不同类型的整数不能进行运算,低位数整数向高位数整数类型转换以后才能运算:
let num2000: UInt16 = 2_000
let num1: UInt8 = 0_001
println("2000 + 1 = \(num2000 + UInt16(num1))")
8.1整数和浮点数转换
整数和浮点数之间的转换必须用Int( )和Double( )显式转换。浮点数向整数转换时总是向上取整,Int (-3.9)是-3。
9.类型同义名
可以用typealias关键字对现有类型进行重命名,提高代码可读性。
typealias AudioSample = UInt16
AudioSample的用法和UInt16完全一样。
10.布尔类型
关键字Bool的布尔类型有两种值:true和false。
布尔类型变量常量多用于条件语句,由于类型安全原则,Swift判断条件一定是布尔型的(区别于C和Java等)。
11.元组
元组可以把各种类型的值集合在一个复合体内,作为整体进行传值。
Swift元组格式和Python元组一样,用括号把元素括起来,元素用逗号间隔。
func intSwap(a : Int, b :Int) -> (Int, Int) {
return (b,a)
}
var a = 1, b = 2
(a,b) = intSwap(a,b)
print("Now a = \(a), ")
println("And b = \(b).")
//prints Now a = 2, And b = 1.
这是一个简单的用元组作为返回类型的整型交换函数,在学习后面的inout关键字后,交换函数还有另一种实现方法。
元组包含的元素类型可以不同,如下面一个元组studentInfo:
let studentInfo = ("JCGuo",20)
var (studentName,studentAge) = studentInfo
println("Is \(studentName) \(studentAge) years old?")
studentName = studentInfo.0
studentAge = studentInfo.1
println("Yes, \(studentName) is \(studentAge) years old.")
可以声明变量接收元组的值,两种赋值模式都可以实现从元组中取出元素的值。第一种方法较为简单,同样用元组的形式去取值;第二种方法默认.0为元组第一个元素,依此类推。我们也可以对元组的元素赋予元素名称,在取值过程用[.元素名称]中取代[.元素序号]来引用:
let studentInfo2 = (name: "JCGuo", age: 20)
studentName = studentInfo2.name
studentAge = studentInfo2.age
println("Yes, \(studentName) is \(studentAge) years old.")
12.可空类型
Swift的可空类型英文是Optional type/Optionals,直译是[可选类型],但是我这里还是根据它的定义把它叫做[可空类型]。
可空类型使用情形是一个可能没有值的变量或常量,它要么有一个值并且能给出具体的值,要么反应自己根本没有值。
Swift表示可空类型直接在普通数据类型后面加上一个问号?,没有声明初始值的可空类型默认初始值为nil。
下面给出一个例子:String类型有一个toInt方法,如果该实例能够转换成Int类型就返回Int值,如果不能转换就返回nil,因而toInt的返回值是一个可空整型Int?:
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
if convertedNumber {
println("Of course I am a number \(convertedNumber!)!")
}
else {
println("I am \(convertedNumber), which means I do not have any value.")
}
输出为:
Of course I am a number 123!,修改代码中[123]为[JCGuo],输出为:
I am nil, which means I do not have any value.。
这个例子有两点注意:
(1)可空类型可以作为控制流的条件,它是nil时相当于布尔型的false,这是使用可空类型的一个很重要的用途。
(2)可空类型变量或常量后面添加后缀 ! 关键字,表示已经知道它里面有值并且把这个值取出来。
我们可以用一个 if-let 语句来简化实现判断过程,Swift称之为可选捆绑[Optional Binding],Java中这种方法也很常见:
let possibleNumber = "1111"
if let convertedNumber = possibleNumber.toInt() {
println("Of course I am a number \(convertedNumber)!")
}
else {
println("I am nil, which means I do not have any value.")
}
注意这个和上面代码的区别,没有感叹号运算符并且else语句中也不能引用convertedNumber,这是因为if let判断过程为:
(1)possibleNumber.toInt()能否实现转换,如果可以,那么声明一个名为convertedNumber的整型Int常量,把可空类型的值赋给它。
(2)如果不能,则执行else块代码,跳过声明名为convertedNumber的常量。
13.断言
可空类型为我们提供了一种优雅的处理缺值现象的手段,但是当你的程序在某个值不存在或者某个值并不满足必要的条件的时候,你的程序无法继续了。在这种情况下,你可以触发一个断言[Assertion]来终止代码执行,进行调试。
Swift支持的断言[Assertion]是一种运行时检查的方法,主要用来调试,你可以检查无效状态发生于哪儿或者查询当前运行状态。
声明一个断言,使用Swift标准函数assert实现。它有两个参数,第一个是有真值的判断条件,第二个是在判断条件为假时输出的反应程序运行状态的String:
let age = -2
assert(age >= 0,"A person's age cannot be less than 0.")
程序在运行时会报出一个
assertion failed异常,它的具体信息是
A person's age cannot be less than 0.
断言一般用于以下三种情况:
(1)整型下标指数超界判断(太小或太大)
(2)排除函数参数有无效值传入
(3)非空的可空类型为后续程序执行的必要条件