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

三) 数组 及常用办法

  1. 创立数组
// 创立整型数组
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]
  1. 快捷创立重复元素的数组
var array4 = Array(repeating: "swift", count: 3) // ["swift", "swift", "swift"]
var array5 = Array(repeating: 1001, count: 3) // [1001, 1001, 1001]
  1. 数组相加
// 2个相同类型的数组相加
var array6 = [1, 2, 3] + [4, 5, 6] // [1, 2, 3, 4, 5, 6]
  1. 常用办法
// 当数组声明为可变时,才干运用增,删,改等办法,常量数组不能进行修正相关操作
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 及常用办法

  1. 创立Set调集
// 创立Set
var set: Set<Int> = [1, 2, 3]
var set2 = Set(arrayLiteral: 1, 2, 3)
  1. 获取元素
// set 获取最小值
set.min()
// 获取第一个元素,次序不定
set[set.startIndex]
set.first
// 经过下标获取元素,只能向后移动,不能向前
// 获取第二个元素
set[set.index(after: set.startIndex)]
// 获取某个下标后几个元素
set[set.index(set.startIndex, offsetBy: 2)]
  1. 常用办法

// 获取元素个数
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
  1. 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]()
  1. 获取元素
// 获取元素个数
dict.count // 3
// 判别字典为空
dict.isEmpty // false
// 获取键对应的值
dict[1] // One
  1. 更新键值对

// 修正键对应的值
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()
  1. 遍历字典

// 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

  1. 运算符:三目,空兼并,区间运算符

// 元组比较巨细。需求元素个数共同,对应的方位的元素类型相同,每一个元素都有必要支持比较运算操作。
// 从第一个元素开端比较,假如没有比较出成果,那么持续顺次比较,直到比出成果为止。
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
  1. 循环: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
  1. 流程操控: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")
}
  1. guard-else 看护判别
// 调用 method
method()
func method() {
    // 看护语句,当 guard 后面的条件成立时,才持续履行,替换之前的 if-return
    guard number > 20 else {
        return
    }
    print("continue execute")
}

七) Swift 函数与闭包

  1. 创立函数

// 创立函数,无参,无回来值,同 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)
}
  1. 函数内外参数命名

// 函数参数指定外部称号
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)
  1. 函数参数指定默许值

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)
  1. 可变参数

// 函数传入多个可变数量的参数,类似于 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的值也被修正了
  1. 函数类型引证,函数嵌套

// 函数能够作为类型进行声明,就像运用其他类型一样
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()
  1. 闭包:后置闭包、逃逸闭包与主动闭包

// 界说闭包,类似于 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 高档[运算符]与枚举

  1. 位运算

// 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
  1. 溢出运算符

// 溢出运算符
var num: UInt8 = 255
var result12 = num &+ 1 // 溢出后变为0
result12 = result12 &- 1 // 溢出后再减1255
result12 = result12 &* 2 // 即 0b11111111 << 1 = 0b11111110 = 254
  1. 重载运算符

// 重载运算符 + , 元组相加,扩展加号的新功能
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)
  1. 自界说运算符

// 自界说运算符
// 自界说前缀运算符,即只需求一个操作数,运算符在操作数前面
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
  1. 枚举

// 界说字符串枚举,原始值类型为 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 结构体与类

  1. 结构体

// 界说结构体
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 特点与办法

  1. 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
  1. 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
  1. 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
  1. 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
  1. 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()
  1. 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[结构办法]

  1. 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)")
  1. 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()
  1. 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)
  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)
  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
  1. 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内存引证与反常处理

  1. 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
  1. 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
  1. 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
  1. 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
  1. 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
  1. 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 中信息
  1. 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
  1. Swift 自界说反常类型

// Swift5 自界说反常类型
enum CustomError: Error {
    case ErrorOne
    case ErrorTwo
    case ErrorThree
}
print("error")
//throw CustomError.ErrorOne // 抛出的反常未捕获会停止,不会打印 complete
print("complete")
  1. 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()
  1. 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…