Swift4.0官方文档学习笔记
2018-07-24 本文已影响55人
优雨
主要记录一下可能容易遗忘的知识点
1.没有隐式类型转换
所有的转换需要显示的进行,例如:
var widthStr = "The width is "
var widthValue = 15
var width = widthStr + String(widthValue)
var num = 12 // num默认为Int类型
var num2 = 12.0 // num2默认为Double类型
2.把值插入字符串的更简单方法
let apple = 2
let banana = 3
let total = "I have \(apple + banana) pieces of fruits"
3.多行字符串
let multiLineStr = """
I am ABC
I like DEF
"""
4.除了数组 字典也用方括号组来创建
let dict = [
"key1" : "value1",
"key2" : "value2"
]
let value1 = dict["key1"]
5.创建空数组或者空字典
- 指定元素类型
let arr = [String]()
let dict = [String:Float]()
- 数组或者字典内元素类型已知 可以用如下方式声明其为空
arr = []
dict = [:]
6.for in循环不再强制需要给for in语句写括号 但是循环体的花括号还是需要的
其他例如if判断、while、repeat-while也是如此
for str in strArr {
print(str)
}
var n = 1
while n < 10 {
n = n * 2
}
7.if语句的判断条件现在必须为布尔表达式 而不能是 if score 这种格式
布尔值的类型为Bool
有true
和false
这两个常量值 和OC中的YES
和NO
不同
可以使用let/var
和if
来对可能为nil
的值进行判断 如果值存在就将值赋予给一个常量或者变量 并执行if
内的语句 这个称为可选项绑定
var optionalName : String? = "Tom"
// var optionName : String? = nil
var greeting = "Hello"
if let name = optionName {
greeting = "Hello \(name)!"
}
8.也可以使用??返回可选类型的默认值
??
对可选项进行判断 如果存在值就返回这个值 否则返回运算符后面的值
var a : Int?
var b = a ?? 10
9.switch语句不需要再写break了 会自动退出当前case
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
10.遍历字典更方便了 只需要提供一对存储键值对的变量就行了
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
print(largest)
11.使用..<创建一个不包含最大值的区间 使用...创建一个包含最大值的区间
其实相当于声明了数组
for i in 0..<4 {
print(i) //输出为0 1 2 3
}
for i in 0...4 {
print(i) //输出为0 1 2 3 4
}
12.函数的声明和调用
func greet(person:String, day:String) -> String {
return "Hello, \(person), today is \(day)!"
}
greet(person:"Bob", day:"Tuesday")
->
表示返回值类型
调用时候要带上实参标签
也可以在申明的时候用_
取消标签
或者声明另一个标签名称
func greet(_ person:String, on day:String) -> String {
return "Hello, \(person), today is \(day)!"
}
greet("Bob", on:"Tuesday")
13.使用元组可以让函数返回一个复合值
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
14.函数可以用...接受多个参数 并放到一个数组里面
func printManyNumber(numbers : Int...) {
for num in numbers {
print(num)
}
}
printManyNumber(numbers: 1,2,3,4) // 传递参数的时候用逗号隔开
15.函数可以内嵌函数 内嵌函数可以访问外部函数的变量
func foo(a : Int) -> Int {
a = a * 2
func bar() {
a = a + 5
}
bar()
return a
}
foo(5)
16.函数可以作为函数的返回值
func getFunc() -> ((Int) -> Int) {
func increase(num : Int) -> Int {
return num + 1
}
return increase
}
var increaseFunc = getFunc()
increaseFunc(1)
17.函数也可以作为函数的参数传递
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)
18.闭包
- 闭包的一般表达式语法为:
{ (parameter) -> returnType in
statements
}
- 举个例子(当函数的最后一个参数为闭包的时候 可以省略函数的括号)
var userNames = ["Tom", "Bob", "Jack"]
userNames.sort{ (name1:String, name2:String) ->Bool in
return name1 < name2
}
- 由于
sort函数
的函数参数的类型已知(即(String, String) -> Bool
)所以闭包可以简化 省略参数的括号和返回类型
userNames.sort{ name1, name2 in
return name1 < name2
}
- 单行表达式闭包可以通过省略
return
关键字来隐式返回单行表达式的结果
userNames.sort{ name1, name2 in name1 < name2 }
- 内联闭包可以省略参数名直接用参数顺序
$0
,$1
,$2
调用
userNames.sort{ $0 < $1 }
- 闭包默认是不允许逃逸的 如果允许逃逸 需要用@escaping声明
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
那么何时闭包允许逃逸呢?比如处理异步回调的时候,异步函数本身是直接返回的,但是异步处理需要异步操作完成之后才进行,这时候的闭包就需要允许逃逸。
- 让闭包 @escaping 意味着你必须在闭包中显式地引用 self
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100"
19.子类重写父类的方法 需要使用override关键字 不使用会造成编译器报错
class Son : Father {
var k
init( j: String , k: Int) {
super.init(j)
self.k = k
}
override func foo() {
print("This is son's foo func")
}
}
let instance = Son()
instance.foo()
20.类型别名
类型别名可以为已经存在的类型定义了一个新的可选名字。用 typealias
关键字定义类型别名。
typealias AudioSample = UInt32
let maxAudioLength = AudioSample.max
21.可选项
var optionalStr : String? = "abc" // 声明一个可选项 optionalStr有可能没有值(nil在swift里表示没有值 对所有类型有效)
let strVal = optionalStr! // 在可选项变量后面加上一个!表示强制展开可选项 如果可选项没有值会报错
let assumedStr : String! = "I have value" // 隐式展开可选项 表示assumedStr被访问的时候一定有值 不需要做检查
22.错误处理
- 当一个函数可能抛出错误时,使用
throws
关键字
func canThrowError() throws {
// statements
}
- 当调用一个可能抛出错误的函数时,使用
try
关键字
do {
try canThrowError()
// 未抛出错误
} catch {
// 抛出错误
}
23.断言和先决条件
断言只在debug模式下检查 先决条件则都会检查
在不满足条件的时候 两者都会终止程序的运行
let age = -1
assert(age >= 0, "Age must be greater than 0")
precondition(index > 0, "Index must be greater than zero.")
24.字符串是值类型
也就是说作为参数传入的时候,传递的是这个字符串的拷贝,在函数里修改字符串对原来的字符串没有任何影响
25.Character类型也用双引号表示
let charA : Character = "A"
let str : String = "ABCDE"
for char in str {
print(char)
}
str.append(charA) // 用append方法可以给字符串后拼接Character
26.可以以Unicode标量形式声明一个字符
let dollarString : Character = "/u{24}" // 24代表Unicode标量码位为U+0024的美元符号"$"
有些特殊字符可以由一个单一的Unicode标量或者几个Unicode标量组合表示 但是在Swift中,都用Character这个类型表示这个字符
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ́
// eAcute is é, combinedEAcute is é
使用count属性获取一个字符串里面Character的数量
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in cafe is 4"
word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in café is 4"
27.字符串的索引
- 字符串不能直接通过整数值索引来访问 需要借助几个特殊的属性和函数
-
.startIndex
返回字符串第一个Character的位置,.endIndex
返回字符串最后一个Character之后
的位置,也就是说.endIndex
不是一个合法的索引 - 使用
index(before:)
和index(after:)
方法来访问给定索引的前后。要访问给定索引更远的索引,你可以使用index(_:offsetBy:)
方法而不是多次调用这两个方法
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a
28.字符串的插入
- 想插入一个字符到指定的索引处,使用
insert(_:at:)
方法
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"
- 想插入字符串到指定的索引处,使用
insert(contentsOf:at:)
方法
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
28.字符串的删除
- 移除指定索引位置的字符,使用
remove(at:)
方法
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"
- 移除指定范围内的字符串,使用
removeSubrange(_:)
方法
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"
29.子字符串
子字符串是是一个Substring的实例,不是另外一个字符串,他会复用父字符串的一部分内存,如果你想让这个子字符串保留的时间长一点,使用String方法将其转变为字符串类型
30.集合类的不变性和可变性
和字符串一样,集合类的可变性也是由声明它的关键字是let\var
来决定的
31.数组相关
- 声明和初始化:
完整写法Array[ElementType]
可简写为[ElementType]
数组
var someInts = [Int]() //简写来初始化一个空数组
let intsArray = [1, 2, 3] // 用字面量语法创建数组 存储的类型自动推断为Int
- 获取元素的数目 使用
count
属性
let intCount = intsArray.count
- 检查是否为空 使用
isEmpty
属性
if intsArray.isEmpty {
print("This is an empty array")
}
- 增删查改
someInts.append(6) // 给末尾增加一个元素
someInts += [8, 10] // 可以使用+运算符或者+=运算符拼接数组
someInts[0] = 0 // 使用下标语法修改某处索引的值
someInts[1...3] = [1, 2, 3] // 使用下标语法还可以修改一定范围内的值
someInts.insert(4, at:4) // 使用insert方法在指定索引处插入值
let removedInt = someInts.remove(at:5) // 使用remove语法移除指定索引处的值 该方法会返回删除后的值
let removedInt2 = someInts.removeLast() // 移除数组末尾的值 返回删除后的值
- 使用普通的
for-in
语法可以遍历数组,但是如果想在遍历的同时获取到索引值,可以使用数组的enumerated()
方法
for (index, value) in intsArray.enumerated() {
print("Item at index \(index) is \(value)")
}
32.合集相关
- 被存入合集的元素必须是可哈希的,也就是必须实现
Hashable
协议(Hashable
协议遵循Equalable
协议),并让其hashValue
属性返回一个合理的Int值 - 声明和初始化,类型声明必须用
尖括号
而不是方括号
,数组,合集,字典里只有合集没有简写语法
var letters = Set<Character>() // 初始化一个存储Character类型的空的合集
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"] // 使用字面量语法初始化 并且显式声明了类型信息 可以省略
- 访问元素数量使用
count
属性 访问是否为空使用isEmpty
属性 和数组一样 - 增删查改
favoriteGenres.insert("Jazz") // 由于合集是无序的 所以直接使用insert方法来添加一个新元素
favoriteGenres.remove("Rock") // 使用remove方法来移除一个元素 被移除的元素同样会被方法返回 可以用 removeAll()来移除合集中的所有元素
// 使用contains方法来检查集合中是否包含了某个元素
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// sorted()方法返回一个使用 < 运算符排序的数组
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
33.字典
- 声明和初始化 完整写法
Dictionary<Key, Value>
,简写为[Key, Value]
,注意简写是用方括号,而不是尖括号
var namesOfIntegers = [Int: String]() // 使用简写初始化一个空字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"] // 使用字面量语法初始化一个字典 并显式声明类型 可以省略
- 字典的
Key
和合集的元素一样,必须都遵循Hashable
协议 - 访问元素数量使用
count
属性 访问是否为空使用isEmpty
属性 和数组一样 - 增删查改 区别较大 分开说
- 下标语法和数组不同 可以添加新元素或者更新值
airports["LHR"] = "London" // 如果`LHR`这个Key已经存在 则更新这个值 否则添加这个值
- 使用
updateKey
方法同样可以添加或者更新值 但是由于这个方法会返回一个可选项,当旧值被更新时,可选项返回旧值 因此可以用这个方法来检查旧值是否被更新了
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
print("The old value for DUB was \(oldValue).")
}
- 使用下标语法从字典的特点键中取回值,返回类型为可选项
if let airportName = airports["DUB"] {
print("The name of the airport is \(airportName).")
} else {
print("That airport is not in the airports dictionary.")
}
- 使用
removeValue(forKey:)
来从字典里移除键值对,返回值为一个可选项,如果删除成功,返回删除的Value,否则返回nil
if let removedValue = airports.removeValue(forKey: "DUB") {
print("The removed airport's name is \(removedValue).")
} else {
print("The airports dictionary does not contain a value for DUB.")
}
- 使用(Key, Value)可以直接对字典进行遍历
for (airportCode, airportName) in airports {
print("\(airportCode): \(airportName)")
}