swift一切的语法
blog.csdn.net/java_androi…
一) 基本数据类型 :
if let temp1 = obj1, let temp2 = obj2, temp1 < temp2 {
// 当全部不为 nil 且满足子句 temp1 < temp2
print(temp1, temp2) // 1 2
} else {
print("obj1 or obj2 may be nil")
}
// 在数值前可加 0 进行位数填充,可加入下划线,添加可读性
var number1 = 001.234 // 1.234
var number2 = 1_234 // 1234
// 打印多个值运用逗号分隔
print(number1, number2) // 1.234 1234
二) Swift 字符串类型及常用办法
“let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning 的值为 "Hello"
// 把成果转化为 String 以便长期存储。
let newString = String(beginning)”
字符串截取:
let index1:String.Index = stre.index(before: stre.endIndex)
let index2:String.Index = stre.index(stre.endIndex, offsetBy: -2)
let str22 = stre[index2...index1]
获取某个字符:
var afterChar = indexStr[indexStr.index(after: startIndex)] // e
字符串的常用办法
blog.csdn.net/java_androi…
range的规模 startIndex...indexStr.index(startIndex, offsetBy: 13)
// 字符串判空
var emptyStr = ""
if emptyStr.isEmpty {
print("string is empty")
}
if emptyStr.count == 0 {
print("string count is 0")
}
// 字符串判巨细,会逐一比较字符巨细
let str1 = "100a", str2 = "101a"
if (str1 < str2) {
print("str1 < str2")
}
// 字符串判持平,会比较一切字符的方位都持平,才为持平的字符串
if (str1 == str2) {
print("str1 < str2")
}
// 运用下标拜访字符
var indexStr = "Hello, William"
// 获取起始下标
var startIndex: String.Index = indexStr.startIndex
var endIndex: String.Index = indexStr.endIndex
// 获取某个下标后一个下标对应的字符
var afterChar = indexStr[indexStr.index(after: startIndex)] // e
// 获取某个下标前一个下标对应的字符
var beforeChar = indexStr[indexStr.index(before: endIndex)] // m
// ... 运算符指定规模,从 startIndex 向后移动4位截取子串
var subStr = indexStr[startIndex...indexStr.index(startIndex, offsetBy: 4)] // hello
// 从endIndex 向前移动7位截取子串
var subStr2 = indexStr[indexStr.index(endIndex, offsetBy: -7)..<endIndex] // William
// 获取规模
var range = indexStr.range(of: "Hello")
// 追加字符串
indexStr.append(Character("."))
indexStr.append(" append string") // Hello, William. append string
// 刺进单个字符到指定方位 Hello, William.# append string
indexStr.insert("#", at: indexStr.index(startIndex, offsetBy: 15))
// 刺进一组字符 Hello, William.-#-# append string
indexStr.insert(contentsOf: ["-", "#", "-"], at: indexStr.index(startIndex, offsetBy: 15))
// 替换指定规模的字符串 How are you.-#-# append string
indexStr.replaceSubrange(startIndex...indexStr.index(startIndex, offsetBy: 13), with: "How are you")
// 删去指定方位的单个字符 How are you.-#-# append strin
indexStr.remove(at: indexStr.index(before: indexStr.endIndex))
// 删去指定规模 -#-# append strin
indexStr.removeSubrange(indexStr.startIndex...indexStr.index(indexStr.startIndex, offsetBy: 11))
// 删去一切字符 ""
indexStr.removeAll()
// 转化巨细写
var uppercase = "hello, swift".uppercased() // HELLO, SWIFT
var lowercase = "HELLO, SWIFT".lowercased() // hello, swift
// 检查前后缀
var hasPrefix = uppercase.hasPrefix("he") // false
var hasSuffix = lowercase.hasSuffix("ft") // true
三) 数组 及常用办法
- 创立数组
// 创立整型数组
var array1: [Int] = [] // []
var arrya2: Array<Int> = [1, 2, 3] // [1, 2, 3]
var arryaInt = [1, 2, 3] // [1, 2, 3]
var array3 = Array(arrayLiteral: 1, 2, 3) // [1, 2, 3]
- 快捷创立重复元素的数组
var array4 = Array(repeating: "swift", count: 3) // ["swift", "swift", "swift"]
var array5 = Array(repeating: 1001, count: 3) // [1001, 1001, 1001]
- 数组相加
// 2个相同类型的数组相加
var array6 = [1, 2, 3] + [4, 5, 6] // [1, 2, 3, 4, 5, 6]
- 常用办法
// 当数组声明为可变时,才干运用增,删,改等办法,常量数组不能进行修正相关操作
var array = [1, 2, 3, 4, 5, 6, 7, 8]
print(array.count) // 8
// 判别数组是空数组
if array.isEmpty {
print("array is empty")
} else {
print("array is not empty")
}
// 经过下标拜访元素
var ele = array[1] // 2
// 截取新数组
var subArray = array[1...2] // [2, 3]
// 获取第一个元素
var firstEle = array.first // 1
// 获取最终一个元素
var lastEle = array.last // 8
// 修正下标对应的元素
array[1] = 22
array // [1, 22, 3, 4, 5, 6, 7, 8]
// 修正指定规模的元素
array[0...2] = [1, 2, 3] // [1, 2, 3]
// 追加单个元素
array.append(9) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 追加一组元素
array.append(contentsOf: [10, 11, 12]) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 在指定方位刺进单个元素
array.insert(0, at: 0) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 在指定方位刺进一组元素
array.insert(contentsOf: [-3, -2, -1], at: 0) // [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 移除指定元素
array.remove(at: 1) // -2
// 移除一组元素
array.removeSubrange(0...2) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 移除首个元素
array.removeFirst() // 1
// 移除结尾元素
array.removeLast() // 12
// 移除前几个元素
array.removeFirst(3) // [5, 6, 7, 8, 9, 10, 11]
// 移除后几个元素
array.removeLast(3) // [5, 6, 7, 8]
// 替换指定规模的元素
array.replaceSubrange(0...3, with: [1, 2, 3, 4]) // [1, 2, 3, 4]
// 判别包括指定元素
if array.contains(3) {
print("array contains 3")
}
// 移除一切元素
array.removeAll() // []
var sortArr = [2, 1, 3, -1]
// 从小到大排序
sortArr.sorted(by: <) // [-1, 1, 2, 3]
// 从大到小排序
sortArr.sorted(by: >) // [3, 2, 1, -1]
// 获取数组最大值
sortArr.min() // -1
// 获取数组最小值
sortArr.max() // 3
界说二维数组
matrix:[[Int]],
matrix[row][column]
var visited = Array(repeating: Array(repeating: false, count: matrix[0].count), count: matrix.count)
matrix[row][col] == path[path.index(path.startIndex, offsetBy: pathIndex)] && !visited[row][col]) {
数组的常用办法
创立 var array4 = Array(repeating: "swift", count: 3) // ["swift", "swift", "swift"]
创立
var array1: [Int] = [] // []
var arrya2: Array<Int> = [1, 2, 3] // [1, 2, 3]
var arryaInt = [1, 2, 3] // [1, 2, 3]
数组相加 +
数组为空isEmpty
数组截取 var subArray = array[1...2] // [2, 3]
数组的元素:
// 获取第一个元素
var firstEle = array.first // 1
// 获取最终一个元素
var lastEle = array.last // 8
常用办法
// 当数组声明为可变时,才干运用增,删,改等办法,常量数组不能进行修正相关操作
var array = [1, 2, 3, 4, 5, 6, 7, 8]
print(array.count) // 8
// 判别数组是空数组
if array.isEmpty {
print("array is empty")
} else {
print("array is not empty")
}
// 经过下标拜访元素
var ele = array[1] // 2
// 截取新数组
var subArray = array[1...2] // [2, 3]
// 获取第一个元素
var firstEle = array.first // 1
// 获取最终一个元素
var lastEle = array.last // 8
// 修正下标对应的元素
array[1] = 22
array // [1, 22, 3, 4, 5, 6, 7, 8]
// 修正指定规模的元素
array[0...2] = [1, 2, 3] // [1, 2, 3]
// 追加单个元素
array.append(9) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 追加一组元素
array.append(contentsOf: [10, 11, 12]) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 在指定方位刺进单个元素
array.insert(0, at: 0) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 在指定方位刺进一组元素
array.insert(contentsOf: [-3, -2, -1], at: 0) // [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 移除指定元素
array.remove(at: 1) // -2
// 移除一组元素
array.removeSubrange(0...2) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 移除首个元素
array.removeFirst() // 1
// 移除结尾元素
array.removeLast() // 12
// 移除前几个元素
array.removeFirst(3) // [5, 6, 7, 8, 9, 10, 11]
// 移除后几个元素
array.removeLast(3) // [5, 6, 7, 8]
// 替换指定规模的元素
array.replaceSubrange(0...3, with: [1, 2, 3, 4]) // [1, 2, 3, 4]
// 判别包括指定元素
if array.contains(3) {
print("array contains 3")
}
// 移除一切元素
array.removeAll() // []
var sortArr = [2, 1, 3, -1]
// 从小到大排序
sortArr.sorted(by: <) // [-1, 1, 2, 3]
// 从大到小排序
sortArr.sorted(by: >) // [3, 2, 1, -1]
// 获取数组最大值
sortArr.min() // -1
// 获取数组最小值
sortArr.max() // 3
数组的遍历
let arr = [11, 22, 33]
for item in arr {
print(item)
}
// 打印数组的下标及对应元素
for item in arr.enumerated() {
print(item) // (offset: 0, element: 11) (offset: 1, element: 22) (offset: 2, element: 33)
}
// 下标遍历
for index in arr.indices {
print(arr[index])
}
四 Swift 调集 Set 及常用办法
- 创立Set调集
// 创立Set
var set: Set<Int> = [1, 2, 3]
var set2 = Set(arrayLiteral: 1, 2, 3)
- 获取元素
// set 获取最小值
set.min()
// 获取第一个元素,次序不定
set[set.startIndex]
set.first
// 经过下标获取元素,只能向后移动,不能向前
// 获取第二个元素
set[set.index(after: set.startIndex)]
// 获取某个下标后几个元素
set[set.index(set.startIndex, offsetBy: 2)]
- 常用办法
// 获取元素个数
set.count
// 判别空调集
if set.isEmpty {
print("set is empty")
}
// 判别调集是否包括某个元素
if (set.contains(3)) {
print("set contains 3")
}
// 刺进
set.insert(0)
// 移除
set.remove(2)
set.removeFirst()
// 移除指定方位的元素,需求用 ! 拆包,拿到的是 Optional 类型,假如移除不存在的元素,EXC_BAD_INSTRUCTION
set.remove(at: set.firstIndex(of: 1)!)
set.removeAll()
var setStr1: Set<String> = ["1", "2", "3", "4"]
var setStr2: Set<String> = ["1", "2", "5", "6"]
// Set 取交集
setStr1.intersection(setStr2) // {"2", "1"}
// Set 取交集的补集
setStr1.symmetricDifference(setStr2) // {"4", "5", "3", "6"}
// Set 取并集
setStr1.union(setStr2) // {"2", "3", "1", "4", "6", "5"}
// Set 取相对补集(差集),A.subtract(B),即取元素归于 A,但不归于 B 的元素调集
setStr1.subtract(setStr2) // {"3", "4"}
var eqSet1: Set<Int> = [1, 2, 3]
var eqSet2: Set<Int> = [3, 1, 2]
// 判别 Set 调集持平
if eqSet1 == eqSet2 {
print("调集中一切元素持平时,两个调集才持平,与元素的次序无关")
}
let set3: Set = [0, 1]
let set4: Set = [0, 1, 2]
// 判别子集
set3.isSubset(of: set4) // set3 是 set4 的子集,true
set3.isStrictSubset(of: set4) // set3 是 set4 的真子集,true
// 判别超集
set4.isSuperset(of: set3) // set4 是 set3 的超集,true
set4.isStrictSuperset(of: set3) // set4 是 set3 的真超集,true
- Set 遍历
// 遍历元素
for ele in set4 {
print(ele)
}
// 遍历调集的枚举
for ele in set4.enumerated() {
print(ele)
}
// 下标遍历
for index in set4.indices {
print(set4[index])
}
// 从小到大排序后再遍历
for ele in set4.sorted(by: <) {
print(ele)
}
四) Swift 字典 Dictionary 调集类型
##1) 创立空字典
var emptyDict1: [Int : String] = [:]
var emptyDict2: Dictionary<Int, String> = Dictionary()
// 指定键值类型
var dict: [Int : String] = [0: "Zero", 1: "One", 2: "Two"]
var dict2: Dictionary<Int, String> = Dictionary(dictionaryLiteral: (1, "One"), (2, "Two"))
// 主动推断键值类型
var dictAuto = [0: "Zero", 1: "One", 2: "Two"]
var dic1=[1:1,2:12,3:32,4:16,5:15]
var dic2:Dictionary<String,String>=[:]
var dic3=Dictionary<String,String>()
var dic4=[String : String]()
- 获取元素
// 获取元素个数
dict.count // 3
// 判别字典为空
dict.isEmpty // false
// 获取键对应的值
dict[1] // One
- 更新键值对
// 修正键对应的值
dict[0] = "000" // 000
// 假如键存在,就更新,否则就新增键值对
dict[-1] = "-1" // -1
// 更新键对应的值,假如键不存在,回来 nil
if let lastValue = dict.updateValue("new one", forKey: 1) {
print("the last value is \(lastValue)") // the last value is One
}
// 移除键值对
dict.removeValue(forKey: -1) // -1
// 移除一切键值对
//dict.removeAll()
- 遍历字典
// dict [1: "new one", 2: "Two", 0: "000"]
// 遍历字典的键
for ele in dict.keys {
print(ele)
}
// 遍历字典的值
for ele in dict.values {
print(ele)
}
// 元组遍历,直接获取键值对
for (key, val) in dict {
print("\(key):\(val)")
}
// 对 key 进行从小到大排序后遍历,并对值进行拆包
for ele in dict.keys.sorted(by: <) {
print(dict[ele]!)
}
//1 读取字典元素
var test1Dic=["key1":"你好","key2":"Swift","key3":"正在学习","key4":"字典","key5":"取值",]
var test1Str=test1Dic["key2"]
println("\(test1Str)")
//此处取字典中未界说的键 不会报错,取出来的值为nil
var test1Str2=test1Dic["key"]
println("\(test1Str2)")
//2 获取字典元素的个数
println(test1Dic.count)
//3 添加字典的元素
test1Dic["key"]="test"
println(test1Dic)
//4 删去字典中的元素
test1Dic.removeValueForKey("key1")
println(test1Dic)
//5 修正字典中的元素
// 5.1 直接修正
test1Dic["key"]="testkey"
// 5.2 运用 updateValue
var oldStr=test1Dic.updateValue("testkeytest", forKey: "key")
println(oldStr)
println(test1Dic)
//6 遍历
//6.1遍历一切的键值对
for (key,value) in test1Dic{
println("key:\(key) value:\(value)")
}
//6.2 遍历一切的键
for test6Str in test1Dic.keys{
println(test6Str)
}
//6.2 遍历一切的值
for test6Str2 in test1Dic.values{
println(test6Str2)
}
//7 字典转数组
//7.1 将一切的键转为数组
var test7Keys=Array(test1Dic.keys)
println(test7Keys)
//7.1 将一切的值转为数组
var test7Values=Array(test1Dic.values)
println(test7Values)
swift 字典常用办法
https://blog.csdn.net/qq_32582087/article/details/49737755
https://wenku.baidu.com/view/2eef2223874769eae009581b6bd97f192279bf3a.html
五) 调集 set 常用办法
**调集的常用**
https://wenku.baidu.com/view/92af6034f9d6195f312b3169a45177232f60e4d0.html
import UIKit
var greeting = "Hello, playground"
// 调集类型:调集 Set
// 不重视次序,但不能够重复
// 创立Set
var set: Set<Int> = [1, 2, 3]
var set2 = Set(arrayLiteral: 1, 2, 3)
// set 获取最大值
set.max()
// set 获取最小值
set.min()
// 获取第一个元素,次序不定
set[set.startIndex]
set.first
// 经过下标获取元素,只能向后移动,不能向前
// 获取第二个元素
set[set.index(after: set.startIndex)]
// 获取某个下标后几个元素
set[set.index(set.startIndex, offsetBy: 2)]
// 获取元素个数
set.count
// 判别空调集
if set.isEmpty {
print("set is empty")
}
// 判别调集是否包括某个元素
if (set.contains(3)) {
print("set contains 3")
}
// 刺进
set.insert(0)
// 移除
set.remove(2)
set.removeFirst()
// 移除指定方位的元素,需求用 ! 拆包,拿到的是 Optional 类型,假如移除不存在的元素,EXC_BAD_INSTRUCTION
set.remove(at: set.firstIndex(of: 1)!)
set.removeAll()
var setStr1: Set<String> = ["1", "2", "3", "4"]
var setStr2: Set<String> = ["1", "2", "5", "6"]
// Set 取交集
setStr1.intersection(setStr2) // {"2", "1"}
// Set 取交集的补集
setStr1.symmetricDifference(setStr2) // {"4", "5", "3", "6"}
// Set 取并集
setStr1.union(setStr2) // {"2", "3", "1", "4", "6", "5"}
// Set 取相对补集(差集),A.subtract(B),即取元素归于 A,但不归于 B 的元素调集
setStr1.subtract(setStr2) // {"3", "4"}
var eqSet1: Set<Int> = [1, 2, 3]
var eqSet2: Set<Int> = [3, 1, 2]
// 判别 Set 调集持平
if eqSet1 == eqSet2 {
print("调集中一切元素持平时,两个调集才持平,与元素的次序无关")
}
let set3: Set = [0, 1]
let set4: Set = [0, 1, 2]
// 判别子集
set3.isSubset(of: set4) // set3 是 set4 的子集,true
set3.isStrictSubset(of: set4) // set3 是 set4 的真子集,true
// 判别超集
set4.isSuperset(of: set3) // set4 是 set3 的超集,true
set4.isStrictSuperset(of: set3) // set4 是 set3 的真超集,true
// 遍历元素
for ele in set4 {
print(ele)
}
// 遍历调集的枚举
for ele in set4.enumerated() {
print(ele)
}
// 下标遍历
for index in set4.indices {
print(set4[index])
}
// 从小到大排序后再遍历
for ele in set4.sorted(by: <) {
print(ele)
}
六) Swift 运算符、循环、流程操控 for-in, while, if-else, switch-case, guard-else
- 运算符:三目,空兼并,区间运算符
// 元组比较巨细。需求元素个数共同,对应的方位的元素类型相同,每一个元素都有必要支持比较运算操作。
// 从第一个元素开端比较,假如没有比较出成果,那么持续顺次比较,直到比出成果为止。
var a = (1, 2, "3")
var b = (1, 2, "4")
var c = a < b // true
// 条件判别
if a > b {
print("a > b")
} else {
print("a < b")
}
// 三目运算,同 java
print(a > b ? "a > b" : "a < b") // a < b
var str: String? = "text"
var result: String = str != nil ? str! : ""
// 空兼并运算符,假如 str 为 nil,则赋值空串,同 kotlin 的 Elvis 运算符 ?:
result = str ?? ""
// 区间运算符,[1, 5],规模是 >=1, <=5,类似于 Kotlin 的区间 1..5
var rang1 = 1...5
// 区间运算符,[1, 5),规模是 >=1, <5
var rang2 = 1..<5
// 判别是否在某个区间规模内
print(rang1 ~= 2) // true
- 循环:for-in, while, repeat-while
// 区间运算符用于循环
for index in rang1 {
print(index)
}
// 中止循环 break
for index in 0...2 {
if index == 1 {
break
}
print(index) // 0
}
// 越过当时循环 continue
for index in 0...2 {
if index == 1 {
continue
}
print(index) // 0 2
}
// 中止外层循环 break,类似于 Kotlin 的限定符
OutterLabel:for outterIndex in 0...2 {
for index in 0...1 {
if outterIndex == 1 {
break OutterLabel
}
print(index) // 0 1
}
}
// while 循环
var i = 0
while i < 3 {
print(i) // 0, 1, 2
i += 1
}
// 即 do-while,先履行一次循环,再判别条件
var k = 0
repeat {
print(k) // 0, 1, 2
k += 1
} while k < 3
- 流程操控:if-else, switch-case
// 流程操控 if-else
let number = 18
if number < 15 {
print("number < 15")
} else if number >= 16 && number <= 20 {
print("number >= 16 && number <= 20")
} else {
print("number > 20")
}
// 流程操控 switch-case
var caseStr = "a"
switch caseStr {
case "a":
print("value is a")
case "b":
print("value is b")
default:
print("default value")
}
// switch 子句多条件匹配
switch caseStr {
case "a","b","c":
print("match success")
default:
print("default value")
}
// switch 子句区间规模匹配
let age = 18
switch age {
case 16..<18:
print("match age 16...18")
case 18...20:
print("match age 18..<20")
default:
print("default value")
}
// switch 元组匹配
let intTuple = (1, 2)
switch intTuple {
case (1, 2):
print("match success 1, 2")
fallthrough // 持续履行后续 case 匹配,不跳出 switch
case (2, 2):
print("match success 2, 2")
fallthrough
case (_, 2):
// 选择性匹配,第一个匿名不重视,只有第二个能匹配,就算匹配成功
print("match success _,2")
fallthrough
case (0...2, 0...2):
// 匹配元组元素的规模
print("match range success")
case (let a, 1):
print("捕获元素: \(a)")
case let(a, b) where a < b:
// 同 (let a, let b),添加 where 字句判别
print("捕获元组: \(a),\(b)")
fallthrough
default:
print("default")
}
- guard-else 看护判别
// 调用 method
method()
func method() {
// 看护语句,当 guard 后面的条件成立时,才持续履行,替换之前的 if-return
guard number > 20 else {
return
}
print("continue execute")
}
七) Swift 函数与闭包
- 创立函数
// 创立函数,无参,无回来值,同 func func1() -> Void
func func1() {
print("no params func")
}
func1()
// 创立函数,带参,带回来类型
func func2(param: Int) -> Bool {
return param > 60
}
func2(param: 80)
// 创立函数,带多个参数,回来类型为元组
func func3(param1: String, param2: Int) -> (result1: String, result2: Int) {
return (param1 + "11", param2 + 20)
}
let tuple = func3(param1: "param", param2: 60)
if tuple.result1.starts(with: "param") {
print(tuple.result2)
}
// 创立函数,带参,回来类型为 Optional
func func4(param: Int) -> Int? {
guard param > 2 else {
return nil
}
return param + 2
}
if let result = func4(param: 3) {
print(result)
}
- 函数内外参数命名
// 函数参数指定外部称号
func outerNameFunc(name1 param1: Int, name2 param2: Int, param3: Int) {
print(param1, param2, param3)
}
// 函数参数运用外部称号
outerNameFunc(name1: 1, name2: 2, param3: 3)
func normalFunc(param1: Int, param2: Int, param3: Int) {
print(param1, param2, param3)
}
// 默许函数参数的内部称号和外部称号共同,调用函数时需求指定参数称号
normalFunc(param1: 1, param2: 2, param3: 3)
// 调用函数时省掉参数称号
func annoFunc(_ param1: Int, _ param2: Int, _ param3: Int) {
print(param1, param2, param3)
}
annoFunc(1, 2, 3)
- 函数参数指定默许值
func func5(param1: Int, param2: Int = 2, param3: Int = 3) {
print(param1, param2, param3)
}
// 调用时,能够只传入没有默许值的参数
func5(param1: 1)
// 调用时,参数方位要严厉对应
func5(param1: 1, param2: 22)
// 函数参数指定默许值
func func6(param1: Int, param2: Int = 2, param3: Int) {
print(param1, param2, param3)
}
// 调用时,参数方位要严厉对应
func6(param1: 1, param3: 33)
- 可变参数
// 函数传入多个可变数量的参数,类似于 Kotlin 的 vararg
func mutableParamFunc(param: Int...) {
var sum = 0
for ele in param {
sum += ele
}
print(sum)
}
mutableParamFunc(param: 1, 2)
mutableParamFunc(param: 1, 2, 3, 4)
// swift 的函数参数值(除引证类型外)默许是不可修正的
func immutableParam(param: Int) {
// param += 1 // 编译失利 error: left side of mutating operator isn't mutable: 'param' is a 'let' constant
}
// 为了能够在函数参数内部修正参数值,能够运用 inout 润饰参数
func immutableParam(param:inout Int) {
param += 1 // 编译经过
print(param) // 2
}
// 调用时需求运用 & 符号
var number = 1
immutableParam(param: &number)
print(number) // 2, number的值也被修正了
- 函数类型引证,函数嵌套
// 函数能够作为类型进行声明,就像运用其他类型一样
let func7Name: (Int, Int) -> Bool
// 将闭包赋值给函数变量
func7Name = {(param1: Int, param2: Int) in
return param1 > param2
}
// 调用函数变量
func7Name(1, 2) // false
// 函数作为参数传入
func func8(funParam: (Int, Int) -> Bool) {
print(funParam(2, 1)) // true
}
// 将 func7 传入 func8
func8(funParam: func7Name)
// 函数作为回来值类型
func func9() -> (Int, Int) -> Bool {
return func7Name // 将 func7Name 回来
}
// 函数嵌套
func outerFunc() {
let outerScope = "outer scope"
func innerFunc() {
print(outerScope, "in inner func")
}
// 在外部函数内调用内部嵌套函数,在外部函数以外无法调用它
innerFunc()
}
// 调用外部函数
outerFunc()
- 闭包:后置闭包、逃逸闭包与主动闭包
// 界说闭包,类似于 Kotlin 的 lambda 表达式。
// 闭包一般是为了处理回调,传递功能代码块
// 闭包标准语法结构:{(param list) -> valueType in block}
let closureFunc1 = {(param1: Int, param2: Int) -> Int in
return param1 + param2
}
// 调用闭包
closureFunc1(1, 2) // 3
// 闭包可省掉回来值
let closureFunc2 = {(param1: Int, param2: Int) in
return param1 + param2
}
closureFunc2(1, 3) // 4
// 假如闭包只有一行代码,能够省掉 return
let closureFunc3 = {(param1: Int, param2: Int) in
return param1 < param2
}
closureFunc3(1, 2) // true
// 入参为闭包
func func10(closureParam: (Int, Int) -> Bool) {
closureParam(2, 1)
}
// 运用默许参数名
func10(closureParam: { $0 > $1 }) // true
// 后置闭包,当最终一个参数为闭包时,简化写法:
func10() {
$0 > $1
}
// 非逃逸闭包:函数的生命周期完毕后,闭包也将被毁掉
// 界说的闭包默许都是非逃逸的
// 逃逸闭包:函数的履行完毕后,闭包在函数外仍可运用
// 界说逃逸闭包运用 @escaping ,一般用于异步回调
func func11(closureParam: @escaping (Int, Int) -> Bool) {
}
// 界说主动闭包运用 @autoclosure,对简略闭包的主动生成。
// 主动闭包默许非逃逸。主动闭包不能够有参数,单表达式
func autoCloseFunc(closureParam: @autoclosure () -> Int) {
print(closureParam()) // 6
}
autoCloseFunc(closureParam: 1 + 2 + 3)
八) Swift5 高档[运算符]与枚举
- 位运算
// Swift 位运算
var sixteen: UInt8 = 0b00010000 // 二进制
print(sixteen) // 8
// Swift 按位与 & : 操作数相同的位进行逻辑与运算
// 即两个对应位的值都为1,成果为1,否则为0。示例:
var result1 = sixteen & 0b00001111 // 0
var result2 = 0b00000111 & 0b00000001 // 1
// Swift 按位或 | :操作数相同的位进行逻辑或运算
// 即两个对应位的值有一个为1,成果为1,否则为0。示例:
var result3 = 0b00000111 | 0b00000000 // 0b00000111 7
var result4 = 0b00000001 | 0b00000010 // 0
// Swift 按位取反 ~ :将操作数的每一位都取反,假如当时位是1,则取反为0
var result5 = ~sixteen // 0b11101111 255 - 16 = 239
// Swift 按位异或 ^
// 即两个对应位的值相同,成果为0,否则为1。示例:
var result6 = 0b00000111 ^ 0b00000000 // 0b00000111 7
var result7 = 0b00000111 ^ 0b00001111 // 0b00001000 8
// Swift 按位左移 << ,按位右移 >>
var result8 = 0b00000111 << 1 // 0b00001110 7 << 1 = 7 * 2 = 14
var result9 = 0b00000111 >> 1 // 0b00000011 7 >> 1 = 7 / 2 = 3
// Swift 按位左移 << ,按位右移 >> 关于位数较低类型,会出现数据丢失的情况
var result10: UInt8 = 0b00001000 << 5 // 0
var result11: UInt8 = 0b00010000 >> 5 // 0
- 溢出运算符
// 溢出运算符
var num: UInt8 = 255
var result12 = num &+ 1 // 溢出后变为0
result12 = result12 &- 1 // 溢出后再减1,255
result12 = result12 &* 2 // 即 0b11111111 << 1 = 0b11111110 = 254
- 重载运算符
// 重载运算符 + , 元组相加,扩展加号的新功能
func +(param1: (Int, Int), param2: (Int, Int)) -> (Int, Int) {
return (param1.0 + param2.0, param1.1 + param2.1)
}
var tuple1: (Int, Int) = (1, 2)
var tuple2: (Int, Int) = (1, 2)
let tuple = tuple1 + tuple2 // (2, 4)
- 自界说运算符
// 自界说运算符
// 自界说前缀运算符,即只需求一个操作数,运算符在操作数前面
prefix operator ++
prefix func ++(param: Int) -> Int {
return param + 1
}
++1 // 2
// 自界说中缀运算符,即需求两个操作数,运算符在两个操作数中间
infix operator **
func **(param1: Int, param2: Int) -> Int {
return param1 * param1 + param2 * param2
}
1 ** 2 // 5
// 自界说后缀运算符,即只需求一个操作数,运算符在操作数后面
postfix operator --
postfix func --(param: Int) -> Int {
return param - 1
}
1-- // 0
- 枚举
// 界说字符串枚举,原始值类型为 String
enum Week: String {
// 在一行中直接界说,也能够别离运用 case 界说
case MON = "星期一", TUE = "星期二", WED = "星期三", THUR = "星期四", FRI = "星期五", SAT = "星期六", SUN = "周日"
}
// 界说整型枚举,原始值类型为 UInt8
enum Number: UInt8 {
// 假如原始值是整型,后续的 case 值会顺次递增
case 壹 = 1, 贰, 叁, 肆, 伍, 陆
}
print(Number.肆.rawValue) // 4
var day = Week.MON
// 结构枚举
var numTwo = Number.init(rawValue: 2)
// case 需求详尽列出
switch day {
case .MON:
print("monday", day.rawValue) // monday 星期一
case .TUE:
print("tuesday")
case .WED:
print("wednesday")
case .THUR:
print("thursday")
case .FRI:
print("friday")
case .SAT:
print("saturday")
case .SUN:
print("sunday")
}
// 界说枚举,设置相关值
enum Direction {
case left(type: Int, text: String)
case right(type: Int, text: String)
}
var direction = Direction.left(type: 1, text: "左")
switch direction {
case let .left(type, text):
print("type: \(type),向\(text)") // "type: 1,向左"
case let .right(type, text):
print("type: \(type),向\(text)")
}
九) Swift 结构体与类
- 结构体
// 界说结构体
struct Phone {
// 界说价格特点
var price: Int
// 界说品牌特点
var brand: String
// 界说类型特点
var model: String
// 界说降价促销办法
mutating func discount() {
price -= 800
}
}
// 调用默许的结构办法,创立结构体实例
let iPhone = Phone(price: 6999, brand: "iPhone", model: "iPhone 13")
print("手机品牌:\(iPhone.brand), 类型:\(iPhone.model),价格:\(iPhone.price)" )
// 结构体归于值类型,用 let 润饰后无法修正 phone 的特点值
var phone = iPhone
phone.price -= 1000
// 值修正后不会影响原结构体的值,iPhone.price: 6999, phone.price: 5999
print("iPhone.price: \(iPhone.price), phone.price: \(phone.price)")
- 类
// 界说一个类
class PhoneClass {
// 界说价格特点
var price: Int = 0
// 界说品牌特点
var brand: String = ""
// 界说类型特点
var model: String = ""
// 界说降价促销办法
func discount() {
price -= 800
}
// 当三个特点都有默许值的时候,能够不写 init
init(price: Int, brand: String, model: String) {
self.price = price
self.brand = brand
self.model = model
}
}
// 创立 class 实例
var huaweiPhone = PhoneClass(price: 5999, brand: "huawei", model: "p40 pro")
// 类归于引证类型,变量传递后,修正值会影响引证的变量
let huaweiNewPhone = huaweiPhone
huaweiPhone.price += 1000
// 值修正后会影响原变量的值,huaweiPhone.price: 6999, huaweiNewPhone.price: 6999
print("huaweiPhone.price: \(huaweiPhone.price), huaweiNewPhone.price: \(huaweiNewPhone.price)")
十) Swift5 特点与办法
- Swift 存储特点
// Swift5 存储特点
class Phone {
var system = "iOS"
// 常量存储特点,一旦实例化,不能修正
let brand: String
// 存储特点,能够修正
var price: Int
// 当类被实例化时,要确保一切的特点都初始化完结,除非特点有默许值
init(brand: String, price: Int) {
self.brand = brand
self.price = price
print("brand: \(brand), price: \(price)")
}
}
// 修正类的特点值
let iPhone = Phone(brand: "iPhone", price: 5999)
iPhone.price -= 600
// 延时存储特点:当类初始化时,延时存储特点不被初始化,当被调用时才初始化
class Consumer {
var money: Int
lazy var phone: Phone = Phone(brand: "iPhone", price: 6999)
init(money: Int) {
self.money = money
}
}
// 只初始化了money
var richMan = Consumer(money: 100_000)
// 延时特点 phone 被初始化
print(richMan.phone) // brand: iPhone, price: 6999
- Swift 核算特点
// Swift5 核算特点
class Android {
// 常量存储特点,一旦实例化,不能修正
let system: String = "android"
// 存储特点
var version = "12"
// api 等级
var apiLevel: String = "31"
// 核算特点,向外提供接口拜访类实例的某种状况,这种状况和类实例的特点值相关联
var info: String {
get {
return "system: \(system), version: \(version), level: \(apiLevel)"
}
set {
// 默许运用 newValue 指代新值
version = newValue.split(separator: "-").first?.description ?? ""
apiLevel = newValue.split(separator: "-").last?.description ?? ""
}
}
// 核算特点 价格,简略模仿
var price: ClosedRange<Int> {
get {
// 当版本高于30时,价格在[4000,6999]之间
if (apiLevel > "30") {
return 4000...6999
} else {
return 1000...3999
}
}
// 自界说传值称号 newPrice
set(newPrice) {
// 当价格高于3999时,版本为31
if (newPrice.lowerBound > 3999) {
apiLevel = "31"
version = "12"
} else {
apiLevel = "30"
version = "11"
}
}
}
}
var newPhone = Android()
print(newPhone.info) // system: android, version: 12, level: 31
newPhone.info = "11-30"
print(newPhone.info) // system: android, version: 11, level: 30
newPhone.price = 4000...4999
print(newPhone.info) // system: android, version: 12, level: 31
- Swift 特点监听器
// Swift5 特点监听器
class iOS {
var brand: String {
// 此特点将要被赋值时会调用,默许带一个 newValue 字段。
// 注意:初始化时不会被调用,从第二次赋值时才开端被调用
willSet {
print("new value : \(newValue)")
}
// 此特点现已被赋值后会调用,默许带一个 oldValue 字段
didSet {
print("old value : \(oldValue)")
}
}
var price: Int {
// 自界说传值称号
willSet(newPrice) {
print("new price : \(newPrice)")
}
// 自界说传值称号
didSet(oldPrice) {
print("old price : \(oldPrice)")
}
}
init(brand: String, price: Int) {
self.brand = brand
self.price = price
print("brand: \(brand), price: \(price)")
}
}
let newIPhone = iOS(brand: "iphone 12", price: 5999)
newIPhone.brand = "iphone 13"
newIPhone.price = 6999
- Swift 特点包装器
// Swift5 特点包装器
@propertyWrapper
struct StringNotEmpty {
var value: String
init() {
self.value = "default string"
}
var wrappedValue: String {
get { return value }
set {
if (newValue.count > 0) {
self.value = newValue
} else {
self.value = "default string"
}
}
}
}
class Student: CustomStringConvertible {
@StringNotEmpty
var name: String
var description: String {
return "student's name is \(name)"
}
}
let student = Student()
student.name = ""
print(student) // student's name is default string
- Swift 静态特点与静态办法
// Swift5 静态特点与静态办法
class BaseClass {
// 静态存储特点
static var param = "param"
// 静态核算特点
static var computeParam: String {
return "computeParam"
}
// 可被承继的静态核算特点
class var openParam: String {
return "openParam"
}
// 声明静态办法,即类办法
static func method() {
print("static method")
}
// 声明可被承继的静态办法
class func openMethod() {
print("static openMethod")
}
}
class SubClass : BaseClass {
// 重写父类的 openParam 特点,类似于 Kotlin 的 open 润饰
override class var openParam: String {
return "SubClass openParam"
}
override class func openMethod() {
print("SubClass openMethod")
}
}
// 调用静态特点
BaseClass.param
BaseClass.computeParam
BaseClass.openParam
SubClass.openParam
// 调用静态办法
BaseClass.method()
BaseClass.openMethod()
SubClass.openMethod()
- Swift 下标办法
// Swift5 下标办法
// 为自界说的数据类型运用 subscript 界说下标拜访元素的办法
class CustomList {
var list: Array<String>
init(list: String...) {
self.list = list
}
// 界说下标办法
subscript(index: Int) -> String {
set {
list[index] = newValue
}
// 能够只界说get
get {
return list[index]
}
}
}
let list = CustomList(list: "1", "2", "3")
list[0] = "item 1"
print(list[1])
十一) Swift5[结构办法]
- Swift 类的结构办法
// Swift5 类的结构办法
// 1. 在结构办法中需求给没有默许值的特点初始化值
class Demo1 {
// 含有默许值
var param1: String = "default"
// 未指定默许值,需求在 init() 中初始化
var param2: String
// 未指定默许值,类型为 Optional,可空,
// 默许值为 nil, 不需求在 init() 中初始化
var param3: String?
init(param: String) {
self.param2 = param
}
}
// 2. 假如特点有默许值,则主动生成一个无参结构办法 init(),即初始化后的实例的特点都有默许值
class Demo2 {
var param1 = "param1 String"
var param2 = "param2 String"
}
var demo2 = Demo2()
print("param1: \(demo2.param1), param2: \(demo2.param2)")
- Swift 结构体的结构办法
// Swift5 结构体的结构办法
struct StructDemo {
var param1: String
var param2: String
// 结构体的结构办法会默许生成,将一切特点作为参数
init(param1: String, param2: String) {
self.param1 = param1
self.param2 = param2
}
init() {
// 在自界说的结构办法中调用默许的结构办法
self.init(param1: "init value1", param2: "init value2")
}
}
// 调用结构体默许的结构办法
var structIns1 = StructDemo(param1: "value1", param2: "value2")
// 调用结构体自界说的结构办法
var structIns2 = StructDemo()
- Swift 指定结构 办法 和 便当结构 办法
指定结构办法 designated 与 便当结构办法 convenience 。运用准则:
- 子类的指定结构办法中有必要调用父类的指定结构办法
- 便当结构办法中有必要调用当时类的其他结构办法
- 便当结构办法最终是要调用指定某个结构办法
// Swift5 指定结构办法和便当结构办法
// 界说一个含有指定结构和便当结构的父类
class Base {
// 默许的指定结构办法
init() {
print("base class designated constructor method")
}
// 声明一个便当结构办法
convenience init(param: Int) {
print("base class convenience constructor method")
// 最终调用指定结构办法
self.init()
}
}
var baseIns = Base(param: 0)
// 承继父类
class Sub : Base {
override init() {
// 假如重写父类的指定结构办法,有必要调用 super
super.init()
}
convenience init(param: Int) {
// 在便当结构办法中调用指定的结构办法
print(param)
self.init()
}
convenience init(param1: Int, param2: Int) {
// 在便当结构办法中调用另一个便当结构办法
print(param1, param2)
self.init(param: param1)
}
}
var subIns = Sub(param1: 0, param2: 1)
- Swift 结构办法的安全性检查
- 有必要在调研父类的指定结构办法前完结本身特点的赋值
- 有必要在调用父类指定的结构办法之后,在子类中才干修正父类的特点值
- 在调用父类的结构办法之后,才干运用 self 关键字
- 在便当结构办法中要修正特点值有必要在调用指定结构办法之后
// Swift5 结构办法的安全性检查
class BaseCheck {
var field: String
init(field: String) {
self.field = field
}
}
class SubCheck: BaseCheck {
var subField: String
init() {
// 1. 有必要在调研父类的指定结构办法前完结本身特点的赋值
subField = "sub field value"
super.init(field: "base field value")
// 2. 有必要在调用父类指定的结构办法之后,在子类中才干修正父类的特点值
field = "base field set in sub"
// 3. 在调用父类的结构办法之后,才干运用 self 关键字
self.subField = "sub field value set again"
print(subField, field)
}
convenience init(param: Int) {
// 4. 在便当结构办法中要修正特点值有必要在调用指定结构办法之后
self.init()
subField = "subField set in convenience \(param)"
field = "field set in conveniencem \(param)"
print(subField, field)
}
}
var checkIns = SubCheck(param: 1)
- Swift 界说可失利的结构办法
// Swift5 界说可失利的结构办法
class CanBeNil {
var field: Int
// 结构可能会失利回来 nil
init?(param: Int) {
guard param > 0 else {
return nil
}
field = param
}
}
let ins = CanBeNil(param: 0) // nil
- Swift 必要结构办法 与 析构办法
// Swift5 必要结构办法与析构办法
class DemoClass {
var field: Int
// 声明必要结构办法,子类有必要承继或重写
required init(param: Int) {
field = param
}
// 析构办法,类实例被毁掉
deinit {
// 实例被开释
print("demo instance destroy")
}
}
// 界说可选类型
var demoIns: DemoClass? = DemoClass(param: 1)
demoIns = nil // 被赋值 nil 时,deinit会调用
十二) Swift 内存办理与反常处理
Swift5内存引证与反常处理
- Swift 内存毁掉机遇
// Swift5 内存毁掉机遇
// 引证类型的内存毁掉机遇
class ClassDemo {
var a = "value a"
deinit {
// 实例被开释
print("deinit class a")
}
}
// 可空类型
var ins1: ClassDemo? = ClassDemo()
var ins2 = ins1
var ins3 = ins2
ins1 = nil // 撤销 ins1 引证
ins2 = nil // 撤销 ins2 引证
print(String(describing: ins3?.a)) // 此处 ins3 引证的实例仍然在,Optional("value a")
// 对实例引证被全部撤销,ClassA 实例此处才毁掉
ins3 = nil // deinit class a
- Swift 单向引证
// Swift5 单向引证
class ClassA {
deinit {
print("deinit ClassA")
}
func foo() {
print("func foo in ClassA")
}
}
class ClassB {
// 此处引证 ClassA 的实例
var ins: ClassA?
init(ins: ClassA?) {
self.ins = ins
}
deinit {
print("deinit ClassB")
}
}
var clzA: ClassA? = ClassA()
var clzB: ClassB? = ClassB(ins: clzA)
// 此处 clzA 所引证的内存并未开释
clzA = nil
// 仍然能够调用 clzB 中的 clzA 实例的 foo 办法
clzB?.ins?.foo() // func foo in ClassA
// 此刻 ClassB 实例被开释,不再有引证指向 ClassA 随即所占内存也被开释
clzB = nil // deinit ClassB \n deinit ClassA
- Swift 循环引证
// Swift5 循环引证
class ClassC {
var insD: ClassD?
deinit {
print("deinit ClassC")
}
func foo() {
print("func foo in ClassC")
}
}
class ClassD {
// 此处引证 ClassC 的实例
var insC: ClassC?
init(ins: ClassC?) {
self.insC = ins
}
deinit {
print("deinit ClassD")
}
}
var clzC: ClassC? = ClassC()
var clzD: ClassD? = ClassD(ins: clzC)
clzC?.insD = clzD
// 此处 clzC 所引证的内存并未开释,对应实例被 clzD 的 insC 引证
clzC = nil
// 仍然能够调用 clzD 中的 insC 实例的 foo 办法
clzD?.insC?.foo() // func foo in ClassC
// 此刻 clzD 的实例仍然被 clzC 的 insD 引证,clzC 和 clzD 实例都未被开释
clzD = nil
- Swift 弱引证 解决 循环引证 问题
// Swift5 运用 弱引证 解决 循环引证
class ClassE {
// 弱引证 weak
weak var insF: ClassF?
deinit {
print("deinit ClassE")
}
func foo() {
print("func foo in ClassE")
}
}
class ClassF {
// 此处引证 ClassE 的实例
var insE: ClassE?
init(ins: ClassE?) {
self.insE = ins
}
deinit {
print("deinit ClassF")
}
}
var clzE: ClassE? = ClassE()
var clzF: ClassF? = ClassF(ins: clzE)
clzE?.insF = clzF
// 此处 clzE 所引证的内存并未开释,对应实例被 clzF 的 insE 引证
clzE = nil
// 仍然能够调用 clzF 中的 insE 实例的 foo 办法
clzF?.insE?.foo() // func foo in ClassE
// 此刻 clzF 的实例被 clzE 的 insF 弱引证,会被毁掉,clzE 和 clzF 实例都能被开释
clzF = nil // deinit ClassF \n deinit ClassE
- Swift 无主引证,针对类型为非 Optional
// Swift5 无主引证,针对类型为非 Optional
class ClassG {
// 无主引证 unowned 假定特点不为 nil
unowned var insH: ClassH
init(ins: ClassH) {
self.insH = ins
}
func foo() {
print("func foo in ClassG")
}
deinit {
print("deinit ClassG")
}
}
class ClassH {
// 此处引证 ClassE 的实例
var insG: ClassG?
deinit {
print("deinit ClassH")
}
}
var clzH: ClassH? = ClassH()
var clzG: ClassG? = ClassG(ins: clzH!)
clzH?.insG = clzG
// 此处 clzG 所引证的内存并未开释,对应实例被 clzH 的 insG 引证
clzG = nil
// 仍然能够调用 clzH 中的 insG 实例的 foo 办法
clzH?.insG?.foo() // func foo in ClassG
// 此刻 clzH 的实例被 clzG 的 insH 无主引证,会被毁掉,clzG 和 clzH 实例都能被开释
clzH = nil // deinit ClassH \n deinit ClassG
- Swift 闭包发生的循环引证
// Swift5 闭包发生的循环引证
class ClassJ {
var field = "field j"
lazy var closure: () -> Void = {
print(self.field)
}
deinit {
print("deinit ClassJ")
}
}
var objJ: ClassJ? = ClassJ()
objJ?.closure()
// 由于闭包引证了类的成员特点,导致实例无法开释,进而导致闭包无法开释,发生循环引证
objJ = nil // 此处并没有打印 deinit 中信息
- Swift 解决闭包发生的循环引证
// Swift5 解决闭包发生的循环引证
class ClassK {
var field = "field k"
lazy var closure: () -> Void = {
// 运用捕获列表对 self 进行无主引证的转化
[unowned self] () -> Void in
print(self.field)
}
deinit {
print("deinit ClassK")
}
}
var objK: ClassK? = ClassK()
objK?.closure()
objK = nil // deinit ClassK
- Swift 自界说反常类型
// Swift5 自界说反常类型
enum CustomError: Error {
case ErrorOne
case ErrorTwo
case ErrorThree
}
print("error")
//throw CustomError.ErrorOne // 抛出的反常未捕获会停止,不会打印 complete
print("complete")
- Swift do-catch 捕获反常,try 履行会抛反常的函数
// Swift5 运用 do-catch 捕获反常,try 履行会抛反常的函数
// 经过函数抛出反常
func funcError() throws -> String {
throw CustomError.ErrorTwo
}
// 运用 do-catch 捕获反常
do {
// 运用 try 履行可能会抛出反常的函数
try funcError()
} catch CustomError.ErrorOne {
print("ErrorOne")
} catch CustomError.ErrorTwo {
print("ErrorTwo")
} catch CustomError.ErrorThree {
print("ErrorThree")
}
// 运用 try? 将函数履行的成果映射为 Optional 类型
let result = try? funcError()
if (result == nil) {
print("exec failed")
}
// try! 强行停止反常的传递,假如发生反常,则程序中止
// try! funcError()
- Swift 函数延时履行结构
// Swift5 函数延时履行结构:防止在抛反常的时候,确保某些有必要的代码块要履行,如开释资源
func lazyFunc() throws -> Void {
defer {
// 函数完毕时会得到履行
print("lazy part of func")
}
print("exec lazyFunc")
throw CustomError.ErrorThree
}
// exec lazyFunc
// lazy part of func
try? lazyFunc()
十三 ) Swift5类型转化泛型、扩展与协议
1. Swift 判别值类型
// Swift5 判别值类型
var anyObj: Any = 1
if anyObj is Int {
print("anyObj's type is Int")
} else if anyObj is String {
print("anyObj's type is String")
}
2. Swift 判别引证类型
// Swift5 判别引证类型
class Base {
var text = "base text"
}
class Sub1: Base {
var subText1 = "sub1 text"
}
class Sub2: Base {
var subText2 = "sub2 text"
func subFunc() {
print("sub func invoke")
}
}
3. Swift 类型转化
// Swift5 类型转化 as , as! , as?
var obj = Base()
var subObj1 = Sub1()
var subObj2 = Sub2()
// Swift 数组中类型为 Base 的都能够存入
var arrayObj: [Base] = [obj, subObj1, subObj2]
for index in 0..<arrayObj.count {
let obj = arrayObj[index]
if obj is Sub1 {
// 假如是 Sub1 就转化为 Sub1 类型,向下转型
let subObj = obj as! Sub1
print(subObj.subText1)
} else if obj is Sub2 {
let subObj = obj as! Sub2
print(subObj.subText2)
} else {
print(obj.text)
}
}
4. Swift AnyObject 与 Any
// Swift 运用 AnyObject 类型声明数组,其间能够寄存任何引证类型,不能够寄存值类型
var arrayAnyObj: [AnyObject] = [obj, subObj1, subObj2]
// Swift 运用 Any 类型声明数组,其间能够寄存任何类型,包括 值类型 和 引证类型
var arrayAny: [Any] = [1, "2", true, obj, (0, 0), {(param: Int) -> Int in return param}]
5. Swift泛型与扩展
// Swift 运用泛型界说办法,打印本身
func printSelf<T>(_ param: T) {
print(param)
}
printSelf("text")
printSelf(1000)
// Swift 运用泛型界说结构体,完成简略调集
struct List<T> {
private var datas: [T] = []
mutating func add(_ newEle: T) {
datas.append(newEle)
}
mutating func get(_ index: Int) -> T {
return datas[index]
}
}
// Swift 运用扩展,给结构体添加一个扩展办法
extension List {
func getDatas() -> [T] {
return datas
}
}
// 界说整型的调集
var list = List<Int>()
// 添加元素
list.add(1)
list.add(2)
list.add(3)
// 读取元素
var ele = list.get(1)
print(ele) // 2
// 调用扩展办法
var datas = list.getDatas()
print(datas) // [1, 2, 3]
6. Swift 泛型束缚
// Swift5 添加泛型束缚
// 界说一个寄存 Base 子类的结构体
struct ObjList<T: Base> {
private var datas: [T] = []
mutating func add(_ newEle: T) {
datas.append(newEle)
}
mutating func get(_ index: Int) -> T {
return datas[index]
}
}
var objList = ObjList<Sub1>()
objList.add(subObj1)
// 界说多个泛型束缚
class MultipleType<T, R> where T: BaseProtocol, R: SubProtocol {
}
7. Swift 协议 protocol
// Swift5 界说协议 protocol,类似于 java, kotlin 中界说接口
protocol BaseProtocol {
// 完成协议时才指定类型
associatedtype T
// 界说一般办法
func printType(input: T) -> Void
// 界说核算特点
var field1: T {get}
var field2: String {get set}
// 界说静态办法
static func method()
}
// 协议承继,主动承继 BaseProtocol 中的特点和办法
protocol SubProtocol: BaseProtocol {
}
// ClaProtocol 协议只能被类恪守
protocol ClaProtocol: AnyObject {
}
8. Swift 恪守完成协议
// Swift5 恪守协议并完成
class ClassImpl: BaseProtocol {
func printType(input: String) {
print(input)
}
// 完成核算特点
var field1: String {
get {return "field1"}
set {}
}
var field2: String {
get {return "field2"}
set {}
}
// 完成静态办法
static func method() {}
}
// 为类扩展特点和办法
extension ClassImpl {
var extField: Int {
get {
return 100
}
}
func extFunc() {
print("ext func")
}
}
var implCla = ClassImpl()
implCla.printType(input: "input text")
print(implCla.extField)
implCla.extFunc()
9. Swift 界说协议可选完成
// 运用 @objc 界说可选完成
@objc protocol OptionalProtocol: AnyObject {
@objc optional func method();
}
extension OptionalProtocol {
// 运用扩展,提供默许完成
func method() {
print("default method extension")
}
}
class ClassOptPro: OptionalProtocol {
}
// 调用默许完成
var claOptIns = ClassOptPro()
claOptIns.method()
十四 ) Swift 高档特性
一、Swift 独占拜访
Swift内存安全检查:当两个变量拜访同一块内存时,会发生独占内存拜访约束。
发生读写权限抵触的情况:
inout 参数读写抵触
结构体中函数修正成员特点读写抵触
值类型特点读写抵触
1. inout 参数读写抵触
// 1. Swift inout 参数读写抵触
var inputStr = "input"
func plusSlef1(_ param: inout String) {
// 在 >= Swift4 版本会抛反常:一起拜访0x103ed30a0,但是修正需求独占拜访。
param += inputStr
}
// 调用下面的代码会溃散
// plusSlef1(&inputStr)
// 一起拜访同一个内存地址,形成读写抵触
func plusSlef2(_ param1: inout String, _ param2: inout String) {
// 在 >= Swift4 版本会抛反常:堆叠拜访'inputStr',但修正需求独占拜访;考虑复制到一个局部变量
let result = param1 + param2
print(result)
}
// 调用下面的代码会溃散
// plusSlef2(&inputStr, &inputStr)
2.结构体中函数修正成员特点读写抵触
// Swift 结构体中函数修正成员特点读写抵触
struct StructA {
var field: Int
// mutating 润饰可修正成员特点,inout 开放写拜访,会发生读写抵触
mutating func edit(_ param: inout StructA) {
field = param.field
}
}
var structA = StructA(field: 100)
// 调用下面的代码会发生编译错误:
// 1. Inout参数不允许互相别名
// 2. 堆叠拜访'structA',但修正需求独占拜访;考虑复制到一个局部变量
// structA.edit(&structA)
3. 值类型特点读写抵触
// Swift 值类型特点读写抵触
class ClassA {
// 界说元组,归于值类型
var tuple = (key1: 1, key2 : 2)
func test1(_ param1: inout Int, _ param2: inout Int) {
print(param1, param2)
}
func test2() {
// 假如被调用会溃散,一起拜访0x600000667cd0,但是修正需求独占拜访。
test1(&tuple.key1, &tuple.key2)
}
func test3() {
// 拜访 局部 值变量 能够正常运用
var localTuple = (key1: 3, key2 : 4)
test1(&localTuple.key1, &localTuple.key2)
}
}
let cla = ClassA()
// 调用下面的代码会溃散
// cla.test2()
cla.test3() // 正常调用,打印 3 4
二、Swift 增强字符串
// 多行字符串 界定符 转义符
// Swift 多行字符串,同 kotlin 的原始字符串,不需求手动添加换行符。可用于排版
var text1 = """
start
\(1)
2
end
"""
print(text1)
// 转义符
var text2 = "对单引号进行转义\'"
print(text2) // 对单引号进行转义'
// 运用界定符替代转义符
var text3 = #"对单引号进行转义'"#
print(text3) // 对单引号进行转义'
// 运用界定符时,转义符失去作用
var text4 = #"换行符1 \n 换行符2"#
print(text4) // 换行符1 \n 换行符2
// 运用界定符时,运用 \# 保留转义符的作用
var text5 = #"换行符1 \#n 换行符2"#
print(text5) // 会换行打印: 换行符1 换行符2
三、Swift 动态成员查找
@dynamicMemberLookup // Swift运用 @dynamicMemberLookup 为类添加动态查找成员的才能
@dynamicCallable // Swift运用 @dynamicCallable 为类添加动态办法调用的才能
class Data {
var field1: Int = 0
var field2: String = ""
subscript(dynamicMember member: Int) -> String {
return "class don't have the field: \(member), type int"
}
subscript(dynamicMember member: String) -> String {
return "class don't have the field: \(member), type String"
}
// 传入一组参数
func dynamicallyCall(withArguments argArray: [Int]) {
print("invoke unknown func with args: \(argArray)")
}
// 传入键值对参数
func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, Int>) {
let argPairs = pairs.map{ key, value in
return "\(key): \(value)"
}
print(argPairs)
}
}
let data = Data()
// 当拜访不存在的特点时,就会调用对应的 subscript 办法回来对应类型的值
// class don't have the field: someInt, type String. class don't have the field: someString, type String
print(data.someInt, data.someString)
// 调用不存在的办法,把实例作为办法调用
// 传入一组参数
data(1, 2, 3) // invoke unknown func with args: [1, 2, 3]
// 传入键值对参数
data(key1: 1, key2: 2) // ["key1: 1", "key2: 2"]
四、Swift 增强协议
// Swift 运用多个协议界定参数
protocol ProtocolA {
var field: String {get set}
}
protocol ProtocolB {
func method()
}
// 完成多个协议
class ClassImpl : ProtocolA, ProtocolB {
var field: String = "impl field"
func method() {
print("impl method")
}
}
// 运用 & 界定多个协议
func testImpl(impl: ProtocolA & ProtocolB) {
print(impl.field)
impl.method()
}
testImpl(impl: ClassImpl())
四、Swift 增强协议
// Swift 运用多个协议界定参数
protocol ProtocolA {
var field: String {get set}
}
protocol ProtocolB {
func method()
}
// 完成多个协议
class ClassImpl : ProtocolA, ProtocolB {
var field: String = “impl field”
func method() {
print("impl method")
}
}
// 运用 & 界定多个协议
func testImpl(impl: ProtocolA & ProtocolB) {
print(impl.field)
impl.method()
}
testImpl(impl: ClassImpl())
参考文献
blog.csdn.net/java_androi…