零、概述
- 类型别名:关键字typealias
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
一、变量、常量、运算符
-
打印:print函数,字符串插值
var nickName:String = "tony" // 字符串插值:打印变量值 print("name\(nickName)")
-
变量和常量的声明
变量声明:var name = "Hui"
,变量值可以被修改。
常量声明:let name = "Hui"
,常量值只能被初始化一次,二次赋值报错。let name = "hui" name = "new hui" // 编译报错:常量类型无法被修改
变量的可变性约束:通过var和let进行约束,let不能被修改,var可以被修改。
例如,可变字符串、可变数组、可变字典等都是定义为var,不可变的定义为let。-
类型推断 与 类型注解
Swift默认支持类型推导(即自动推测变量的类型),也支持类型注解(即明确声明变量的类型);// 类型推导:name自动推导为Sting类型 var name = "Hui" // 类型注解:nickName明确为String类型 var nickName:String = "tony"
-
类型检查(因此,类型安全)
变量的类型一旦确定,就无法更改;如果赋不同类型的值,编译器会报错。
这是因为,明确类型后的变量的内存布局已经完成。var name = "Hui" name == 123 // 报错:类型不匹配
2、内置变量
数值型字面量:即数值的表示方法
- 一个十进制数,没有前缀
- 一个二进制数,前缀是 0b
- 一个八进制数,前缀是 0o
- 一个十六进制数,前缀是 0x
let decimalInteger = 17
let binaryInteger = 0b10001 // 二进制的17
let octalInteger = 0o21 // 八进制的17
let hexadecimalInteger = 0x11 // 十六进制的17
类型转换问题
- 不同类型变量或常量能存储的数值范围是不同的,如果数值超出了常量或者变量可存储的范围,编译的时候会报错。
- 不同数值类型的变量相加,编译器会报错。
let value1:UInt8 = 10
let value2:UInt16 = 10
// Binary operator '+' cannot be applied to operands of type 'UInt8' and 'UInt16'
let count = value1 + value2
元组(tuples) —— 新增
- 定义:把多个值组合成一个复合值,元组内的值可以是任意类型。
let http404Error = (404, "Not Found")
- 元组的内容解析:即访问元组的内部变量
// 1、元组的内容分解:可以将一个元组的内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们.
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// 2、可以把要忽略的部分用下划线(_)标记:
let (justTheStatusCode, _) = http404Error
// 3、通过下标来访问元组中的单个元素,下标从零开始:
print("The status code is \(http404Error.0)")
print("The status message is \(http404Error.1)")
// 4、可以在定义元组的时候给单个元素命名:
let http200Status = (statusCode: 200, description: "OK")
// 无需内容分解,直接使用
print("The status code is \(http200Status.statusCode)")
print("The status code is \(http200Status.description)")
可选类型 与 可选类型解析 —— 新增
- 可选类型表示两种可能:或者有值,或者根本没有值。
- 语法:类型后面跟问号,
类型?
var nilValue: String? = "Tom"
- nil:表示它没有值。
注意:非可选类型的变量,初始化无法显示赋值为nil。
// 编译报错:'nil' cannot initialize specified type 'String'
var nilValue:String = nil
可选类型解析(即访问 可选类型 变量)
-
强制解析
在可选值后面加一个感叹号(!
)来获取值,这个惊叹号表示"我知道这个可选有值,请使用它"。
var nilValue:String? = "name"
if nilValue != nil {
// 强制获取 可选类型变量 nilValue 的值
print(nilValue!)
}
-
可选绑定解析
用来判断可选类型
是否包含值,如果包含就把值赋给一个临时常量或者变量。
可选绑定可以用在 if 和 while 语句中。如下
if let name = nilValue {
// 有值则解析值到name变量
print(name)
} else {
// nil,没有值分支
}
隐式解析的可选类型
- 定义:即变量在第一次赋值之后,就确定之后一直有值。
- 语法:
类型!
,其无需强制类型解析
let assumedString: String! = "An implicitly unwrapped optional string."
// 控制判断
if assumedString != nil {
let implicitString: String = assumedString
print(implicitString)
}
-
隐式解析可选类型
同样支持可选类型解析
if let definiteString = assumedString {
print(definiteString)
}
3、常用的内置类型
- 整数:Int、Unit、Int8、Int32等。
- 浮点数:Double —— 表示64位浮点值,Float —— 表示32位浮点值
- 布尔值:Bool(true、false)
字符串
- 单行和多行字符串
let singleLineString = "These are the same."
let multilineString = """
These are the same.
"""
- 基础操作
let nickName:String = "Hello World"
print(nickName.isEmpty)
print(nickName.count)
print(nickName.utf8)
print("say " + nickName)
print(nickName.appending("!"))
print(nickName.hasPrefix("He"))
print(nickName.hasSuffix("World"))
// 遍历字符串里的字符
for ch in nickName {
print(ch)
}
// 字符串相等
let n1 = "123"
let n2 = "abc"
print(n1 == n2) // false
print(n1 != n2) // true
- 字符串的访问
let nickName:String = "Hello World"
print("start=\(nickName.startIndex), end=\(nickName.endIndex)")
print(nickName[nickName.startIndex])
print(nickName[nickName.index(after: nickName.startIndex)])
print(nickName[nickName.index(before: nickName.endIndex)])
print(nickName[nickName.index(nickName.startIndex, offsetBy: 3)])
for index in nickName.indices {
print("\(nickName[index]) ", terminator: "")
}
- 字符串的插入和删除
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome 变量现在等于 "hello!"
welcome.insert(contentsOf:" there", at: welcome.index(before: welcome.endIndex))
// welcome 变量现在等于 "hello there!"
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome 现在等于 "hello there"
// 支持:区间运算符
let range = welcome.index(welcome.endIndex, offsetBy: -6) ..< welcome.endIndex
welcome.removeSubrange(range)
// welcome 现在等于 "hello"
- 子字符串(其实质是一个 SubString 的实例)
// 1、prefix
print(greeting.prefix(2))
// 2、数组下标
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning 的值为 "Hello"
print(beginning)
// 3、把结果转化为 String 以便长期存储。
let newString = String(beginning)
print(newString)
在 Swift 中, String 类型 是 值类型。
如果你创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。字符串插值:
\(变量)
,即把变量的值插入到字符串中
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
集合类型(数组、集合、字典)
-
数组、集合、字典它们之间的差别如下:
集合类型的可变性:var可变,let不可变(编译器会优化不可变集合类型,以达到内存最优)。
数组(Array)
- 数组的创建
func testArray() {
// 1、声明具体类型数组
var someInts = [Int]()
print(someInts)
// 编译报错:Cannot convert value of type 'Double' to expected argument type 'Int'
//someInts.append(10.0)
someInts.append(1)
print(someInts.count)
// 数组清空
someInts = []
print(someInts)
// 2、构造函数创建:带有默认值的数组
let doubles_1 = Array(repeating: 0.0, count: 3)
let doubles_2 = Array(repeating: 10.0, count: 6)
print(doubles_1 + doubles_2)
// 3、字面量构造数组
var shoppingList: [String] = ["123", "Eggs", "Milk"]
shoppingList[0] = "Apples"
print(shoppingList[0])
print("区间运算符:\(shoppingList[1...2])")
// 数组遍历
for val in shoppingList {
print(val)
}
for (index, value) in shoppingList.enumerated() {
print("list[\(index+1)] = \(value)");
}
shoppingList.append("Pear")
print(shoppingList.isEmpty)
// 3、插入和删除
shoppingList.insert("err", at: 0)
shoppingList.remove(at: 0)
print(shoppingList)
shoppingList.insert("1", at: 0)
shoppingList.append("2") // 末尾添加
print("删除最后一个:\(shoppingList.removeLast())")
print("删除第一个:\(shoppingList.removeFirst())")
print(shoppingList)
}
字典Dictionary<Key, Value>
func testDic() {
// 1、创建:具体类型声明字典
var namesOfIntegers = [Int: String]()
namesOfIntegers[16] = "sixteen"
print(namesOfIntegers)
// 赋空字典
namesOfIntegers = [:]
print(namesOfIntegers)
// 2、创建:字面量创建字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports)
let airports_1 = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports_1)
// 访问
print(airports.count)
print(airports.isEmpty)
airports["LHR"] = "London"
print(airports)
// 删除
airports["APL"] = "Apple Internation"
airports["APL"] = nil
print(airports)
airports.removeValue(forKey: "LHR")
print(airports)
// 遍历
for (key,value) in airports {
print("key:\(key), value:\(value)")
}
print("allKeys:\(airports.keys)")
print("allValues:\(airports.values)")
}
二、运算符
以下只列出Swift特有的,其他大致同C语言类似。
- 赋值运算符:Swift 的赋值操作并不返回任何值。
// 此句错误,因为 x = y 并不返回任何值。这样可以避免把 (==)错写成(=)这类错误的出现。
if x = y {
...
}
- 区间运算符
闭区间运算符:a...b
,包括b,a不能超过b。
半开区间运算符:a..<b
,不包括b,a不能超过b。
for index in 0...5 {
print(index)
}
let names = ["Anna", "Alex", "Brian", "Jack"]
for i in 0..< names.count {
print(names[i])
}
- 单侧区间运算符
闭区间的单侧闭区间:如names[2...]/names[...2]
半开区间的单侧闭区间:如names[..<2]
for name in names[2...] {
print(name)
}
// Brian
// Jack
for name in names[...2] {
print(name)
}
// Anna
// Alex
// Brian
for name in names[..<2] {
print(name)
}
// Anna
// Alex
- 恒等
===
和 不恒等!==
运算符:用来判断 两个对象 是否引用同一个 对象实例。
let s1 = "123"
let s2 = "123"
// true
print(s1 == s2)
这两个运算符无法用于 值类型
的变量或常量。
class Person {
var name = ""
}
let p1 = Person()
let p2 = Person()
print(p1 === p2)
/*
2、 值类型
*/
struct Stack {
var counts = 0
}
let st1 = Stack()
let st2 = Stack()
// error: argument type 'Stack' expected to be an instance of a class or class-constrained type
print(st1 === st2)
// error: argument type 'String' expected to be an instance of a class or class-constrained type
print(s1 === s2)
-
空合运算符:针对可选类型的判空判断
a ?? b
将对可选类型 a 进行空判断,如果 a 包含一个值就进行解包,否则就返回一个默认值 b。
注意:表达式 a 必须是 Optional 类型;默认值 b 的类型必须要和 a 存储值的类型保持一致。a ?? b
等价于a != nil ? a! : b
三、控制流
1、其他与C语言大致一样,但Swift是不需要额外的括号,如下
while square < finalSquare {
...
}
if a < b {
} else if {}
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
} else {
print("It's not that cold. Wear a t-shirt.")
}
2、新特性
支持
for-in
循环(如上数组字典遍历)支持
repeat-while
(等同于do-while
)
repeat {
statements
} while condition
3、Switch —— 功能得到极大的加强
注意:不存在隐式的贯穿(如需要手动贯穿,如下
fallthrough
)。
与 C 和 Objective-C 中的 switch 语句不同,在 Swift 中,当匹配的 case 分支中的代码执行完毕后,程序会终止 switch 语句,而不会像C语言继续自动的执行下一个 case 分支。case:复合型,即多个分支合并成一个分支,逗号分开
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
// 输出“e is a vowel”
- case:区间匹配
switch count {
case 0:
...
case 1..<5:
...
}
case 和 元组 搭配使用
- case:元组匹配(下划线
_
来匹配所有可能的值)
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) is at the origin")
case (_, 0):
print("\(somePoint) is on the x-axis")
case (0, _):
print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
print("\(somePoint) is inside the box")
default:
print("\(somePoint) is outside of the box")
}
// 输出“(1, 1) is inside the box”
- case:值绑定(Value Bindings) —— 类似于
元组的内容分解
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// 输出“on the x-axis with an x value of 2”
- case:支持
where
条件判断
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// 输出“(1, -1) is on the line x == -y”
4、控制转移语句
continue、break、return
fallthrough:
用于switch中,从一个case跳到下一个case;这是因为Swift中的switch是执行完case不会在执行下一个case,所以实现C语言的Switch贯穿特性。带标签的语句:
label xxxName: 代码块
label xxxName: while condition {
statements
}
-
guard
语句,提前退出
要求条件必须为真时,才继续执行 guard 语句后的代码,否则退出。
func greet(person: [String: String]) {
guard let name = person["name"] else {
return
}
print("Hello \(name)!")
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}
greet(person: ["name": "John"])
// 输出“Hello John!”
// 输出“I hope the weather is nice near you.”
greet(person: ["name": "Jane", "location": "Cupertino"])
// 输出“Hello Jane!”
// 输出“I hope the weather is nice in Cupertino.”
-
#available(...)
检测API的可用性
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}