Fork me on GitHub

Swift学习笔记

Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
// repeating 重复
var threeDoubles = Array(repeating: 0.0, count: 3)
// +=
threeDoubles+=threeDoubles;

threeDoubles.append(10.0)
threeDoubles.append(contentsOf: [1,1,1,1])

threeDoubles.insert(1.0, at: 0)
threeDoubles.insert(contentsOf: [10.0], at: 0)

var chars: [Character] = ["a"]
chars.insert(contentsOf: "heii", at: 0)

var cc = ""
cc.insert(contentsOf: "cc", at: "".startIndex)
cc.insert("c", at: "".startIndex)
let c11: Character = "a"
var arr = Array(1...100)


arr.remove(at: 0)
arr.removeFirst()

// 从头开始删除xxx个obj
arr.removeFirst(1)
// 从尾开始删除xxx个obj
arr.removeLast(1)
arr.removeSubrange(1...2)
// 删除最后一个obj
arr.popLast()

// 删除obj 是否保留容量
arr.removeAll(keepingCapacity: false)

// 特殊初始化
var numbers = Array(1..<7)
var numbers1 = [Int](1..<7)
[Int]([2222:"",222:""].keys)
[Int]([2222:"",222:""].keys)
Array([2222:"",222:""].keys)
let a = [Character]("abccc")
let a1 = Array<Character>("abccc")
let a2 = Array("abccc")

// 块替换
// 把 4 5 6 这部分换为 [100, 200] 会操作数组的个数
// [100,200,4,5,6,7,8]
var arr1 = [1,2,3,4,5,6,7,8]
arr1[0...2] = [100, 200]


// for-in
for _ in ["1", "2"] {}
for (_, _) in ["1", "2"].enumerated() {}
for _ in 1...2 {}
for _ in 1..<2 {}
// 倒序
for item in [1,2,10].reversed() {
print(item)
}

// 跳动循环
// 2 4 6 8 10 12
for _ in stride(from: 2, through: 12, by: 2) {}

// forEach 和 oc enum差不多 不可以使用 break 和 comm来控制循环
// 原理和oc的enum遍历类似 return 只可以退出此次循环
[""].forEach { (item) in
}

// enumerated
// reversed 倒序
for (_, _) in ["1"].enumerated().reversed() {
}

// 迭代器
var makeIterator = [Int](2...20).makeIterator()
while let num = makeIterator.next() {
print(num)
}

[1].startIndex
[1].endIndex
[1].count

// indices 来遍历 arr 的索引区间进行遍历
for i in ([Character]("abc")).indices {
print(i)
}
let rang1 = ([Character]("abc")).indices
let rang2 = (1...2)

// arr 是否包含 obj
// [1].contains(<#T##element: Int##Int#>)
// 遍历数组中是否包含指定obj 但具体是否包含是自己实现的
let c = [1,100,200].contains { (num) -> Bool in
print("==\(num)")
if num == 111 {
return true
}
return false
}
[1,100,200].contains {
(num) -> Bool in
return false
}

// 是否全部obj 满足xx条件
[1].allSatisfy { (num) -> Bool in
return false
}
// 简写 $0
[1].allSatisfy({$0 > 10})

// 获取第一个obj
[1].first
// 获取第一个满足xxx条件的obj
[1].first { (num) -> Bool in
return false
}
// 在数组中第一个为aa 的元素的位置
[""].firstIndex(of: "aa")
// 获取第一个满足xxx条件的obj的index
[1].firstIndex { (num) -> Bool in
return false
}
// 同理
[1].last


// min max
[1].min()
[1].min { (num, num2) -> Bool in
return false
}
[1].min {$0 > $1}

[1].max()
[1].max { (n1, n2) -> Bool in
return false
}



// ArraySlice arr切片 和 Substring 类似,共享内存
// drop 踢出xxx 返回一个 new 的 ArraySlice
let arrs = [1,2,3,4,4,5][1...2]
// 踢出第一个 得到第1个到最后一个的 ArraySlice(切片Arr)
[1].dropFirst()
// 踢最后一个 得到的arr
[1].dropLast()
// 从后面开始踢几个 得到的arr
[1].dropLast(1)
// 从前面开始踢几个 得到的arr
[1].dropFirst(1)
// 踢出满足条件的obj 得到的arr
[1].drop { (num) -> Bool in
return false
}

// 获取数组前面的obj xxx个
[1].prefix(1)
// 获取数组前面的obj 到xxx位置 不包括xxx位置,1=表示到索引0 和prefix(1)结果一样
[1].prefix(upTo: 0)
// 获取数组前面的obj 到xxx位置 包括xxx位置,1=表示到索引1
[1].prefix(through: 0)
// 从前面开始获取满足条件的 obj 到y第一个不满足就停止
[1].prefix { (num) -> Bool in
return false
}

// 取最后的固定长度
[1].suffix(1)
// 从指定索引xxx到结束 (包含指定索引)
[1].suffix(from: 0)

// rang
[11,1,1,1,1][1...2]
[1,1,1,1,1][...]
[11,1,1,1,1][1..<2]

let a111 = Array([1][...])
let a112 = [1][...]


// 重排操作
// 随机打乱 arr 顺序
var shuffleArr = [1]
shuffleArr.shuffle()
// 随机打乱数组顺序 同时返回 原arr不改变
[1,1,1,1,1,1].shuffled()

// 逆序
// 把 arr 逆序 修改原arr
shuffleArr.reverse()
// 把 arr 逆序 不改原arr
[1].reversed()


// 分组 partition
// 把 arr 由xxx条件分组,系统会自动把满足条件的 放在前面,不满足的放在后面
// 返回分割点的 index
// 系统不保障obj之间的顺序 顺序快一点打乱 主要是把满足条件在z前面就行
shuffleArr.partition { (num) -> Bool in
return false
}

// 排序
shuffleArr.sort()
shuffleArr.sorted()
shuffleArr.sort { (n1, n2) -> Bool in
return false
}
shuffleArr.sorted { (n1, n2) -> Bool in
return false
}

// 交换
shuffleArr.swapAt(0, 0)


// 字符串数组拼接
// 把字符串数组直接拼接起来
["zzz","a"].joined()
// 把字符串数组用 xxx 拼接起来
["zzz","a"].joined(separator: ",")
// Sequence 序列性质的数组也可以拼接
for item in [1...2, 10...20].joined(separator: 2...3) {
// 1 2 10 ... 20
print(item)
}
for item in [[1,2],[222,222222]].joined(separator: [1,2]) {
print(item)
}

// arr 的底层实现
//Sequence;
//Collection;
//RangeReplaceableCollection;
//Array;

// 使用 arr 实现 Stack
struct Stack<T>{
private var es = [T]()

var count: Int {
return es.count
}

var isEmpty: Bool {
return es.isEmpty
}

func pop() -> T? {
return es.last
}
}

Set



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// set 中的 obj 必须是可哈希的就和 dict的key一样必须可以哈希
// 可哈希才可以判断是否已经存在
// 默认系统值类型都是可以哈希的
// 自定义类型可以实现哈希即可
let set1 = Set<String>()
var set2: Set<String> = ["a"]
set2.insert("cc")

for _ in set2 {}

for _ in set2.sorted() {}

// 由set->arr
//set2.sorted(by: <#T##(String, String) throws -> Bool#>)
//set2.sorted()
//set2.isEmpty
//set2.count

// 插入
//set2.insert(<#T##newMember: Hashable##Hashable#>)
// 更新obj 哈希一样时就更新 没有时就增加
//set2.update(with: "bb")
print(set2)
set2.update(with: "aaaaaa")
print(set2)

// 过滤
// 得到一个新的 set 是满足条件的 obj
set2.filter { (num) -> Bool in
return false
}
// 得到一个新的 arr 是满足条件的 obj
set2.filter { (num) -> Bool in
return false
}

// 暂未理解这个
//set2.remove(at: <#T##Set<String>.Index#>)

// 算法 获取 set 的所有子集

// 底层实现

Dictionary

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Dictionary<String, Int>()
[String: Int]()
let dic: Dictionary<String, Int> = [:]
var dic1: [String: Any] = ["aaaaa": 100, "a": ""]
["": 1].count
["": 1].isEmpty

for (k, v) in ["": 1] {
}

for k in ["": 1].keys {
}

for k in ["": 1].values {
}

for k in ["": 1].values.sorted() {
}
// 其他和arr的操作类似


var dict1 = [String: Int?]()
// add obj
dict1["a"] = 100
// 移除obj
dict1["a"] = nil
// 更新或者添加obj
dict1.updateValue(100, forKey: "a")
dic1.remove(at: dic1.startIndex)

do {
// merge 把一个dic合并到另一个dic中去
var dict1 = ["a": 10]
// dic 把后面的 dic合并到前一个dict中,同key时使用条件来控制
// b1 是前一个dic
// b1 是后一个dic
dict1.merge(["a": 1]) { (b1, b2) -> Int in
return b1
}
print(dict1)

// merging 把2个dic合并 得到一个新 dic
do{
let dict1 = ["a": 10]
let dic = dict1.merging(["a": 1]) { (b1, b2) -> Int in
return b1
}
print(dic)
}

do {
// 字典位置暂时无考虑
// firstIndex
}

// KeyValuePairs
// 一种特殊的dic,拥有顺序,理解为是有顺序的 dict
do{
let dic = KeyValuePairs<String, Int>()
print(dic)

let dic1: KeyValuePairs = ["a": 100,"b": 100]
print("KeyValuePairs")
print(dic1)

do {
let dic1: Dictionary = ["a": 100,"b": 100]
print("Dictionary")
print(dic1)
}

}
}

String Substring String.Index

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
let str = "a"
var str1 = "a"
var str2 = """
abcd
abcd
"""

var str3 = """
abcd\
abcd
"""

var str4 = "a*a\(77*2)"

str1+=""
str1 = "1"+"1"
str1 == str2

// String.Index
// 取下标不可以用 endIndex
"abc".startIndex
"abc".endIndex
"abc"["abc".startIndex]
"abc"["abc".index(before: "abc".endIndex)]
"abc"["abc".index(after: "abc".startIndex)]
"abc".index("abc".startIndex, offsetBy: 1)

// Substring
"abc".startIndex..<"abc".endIndex
"abc"["abc".startIndex..<"abc".startIndex]
"abc"["abc".startIndex..<"abc".endIndex]

// 从前面开始取2个长度
"abc".prefix(2)
// 从前面开始取到指定位置
"abc".prefix(upTo: "abc".index(after: "abc".startIndex))
// 是否为这个前缀
"abc".hasPrefix("abc")
// 取后面的x位
"abc".suffix(2)
// 从x位置开始取
"abc".suffix(from: "abc".startIndex)
"abc".hasSuffix("abc")

// 字符串分割
for item in "a b c".split(separator: " ") {
let str = String(item)
print(str)
}


// 为 String 增加功能

import Foundation

extension String {

// 获取从开头开始到指定xxx位置的字符串
func subString(to index: Int) -> String {
return self[0..<index]
}

// 获取从xxx位置开始到结束的字符串
func subString(from index: Int) -> String {
return self[index..<self.count]
}

// 获取指定范围的字符串
subscript (r: Range<Int>) -> String {

let start = self.index(self.startIndex, offsetBy: r.lowerBound, limitedBy: self.endIndex) ?? self.endIndex
let end = self.index(self.startIndex, offsetBy: r.upperBound, limitedBy: self.endIndex) ?? self.endIndex
return String(self[start..<end])
}

// 获取指定位置的字符串
subscript (n: Int) -> String {
return self[n..<n+1]
}

// 获取指字符串在字符串中的范围
subscript (str: String) -> Range<Index>? {
return self.range(of: str)
}
}

运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// 运算符
let a = false
!a

var num = 10
-num
+num
num+=1
num-=1
num*=1
num/=1
num > 1 ? "num>1" : "num<=1"


// 可以溢出运算,循环运算
// &+
// &-
// &*

// 0
UInt8.max&+1
// 1
UInt8.max&+2

// 255
UInt8.min&-1
// 254
UInt8.min&-2

UInt8.min&*1
UInt8.min&*2

// 合并空值运算符
// ?? 如果有值就使用它的值,不然就使用默认值
var num1: String? = String()
num1 = nil
num1 ?? "abc"
(num1 != nil) ? num1 : "abc"

func addTwoNum(num1: Int?, num2: Int?) -> Int {
return (num1 ?? 0) + (num2 ?? 0)
}

// 区间运算符
0...10
0..<10

for _ in [1,2,3,4][..<2] {
}

for _ in [1,2,3,4][...2] {
}

for _ in [1,2,3,4][0...] {
}

let rang = ...10
// 是否包含指定数字
rang.contains(10)
rang.contains(11)
rang.contains(-1)
rang.contains(-1000)


for item in [1,2,10].reversed() {
print(item)
}

for item in (1..<6).reversed() {
print(item)
}

// true
("a"..."z").contains("a")
// false
("a"..."z").contains("-")


// 位运算
// ~ 取反运算符
// 把数据的二进制位全部取反 1->0 0->1
let num5 = 10
~num5

// 与运算符 对二进制操作 一假即假
// 1&1 = 1
// 0&1 = 0
// 1&0 = 0
// 0&0 = 0
1&1

// 或运算符 对二进制操作 一真即真
// 1&1 = 1
// 0&1 = 1
// 1&0 = 1
// 0&0 = 0
1|1


// 位异或 互斥或 (对二进制操作 同假异真)
//
1^1

// 无符号的左移 右移
// 左移 右移 运算符 << >>
// 全部二进制向左或者右移x位,超出的丢掉,空出来的补0
// 减半和加倍算法

// 有符号的左移 右移操作暂时未展开
// 寻找成对的无符号数丢失的数可以使用 ^ 来处理

// 这里可以对一些特殊的算法使用 ^ 来快捷处理。


// 运算符重载
// 类和结构体可以为现在的运算符提供其他的实现方式
// 如:向量的加法,我们可以使用自定义的结构体同时配合 + (加法)来处理
// 如:class d也可以定义一些特殊的类型来,做类似的 + (加法)运算

struct Vector2D {
var x = 0.0
var y = 0.0
}

extension Vector2D {
// 双目运算符
// 给结构体处理了 + 运算 (双目运算符)
static func +(right: Vector2D, left: Vector2D) -> Vector2D {
return Vector2D.init(x: 1, y: 1)
}

// += 需要 inout 来处理可以修改
static func +=(right: inout Vector2D, left: Vector2D) -> Vector2D {
return Vector2D.init(x: 1, y: 1)
}

// 单目运算符
// 单目运算符 prefix 或者 postfix 前缀来修饰
static prefix func !(right: Vector2D) -> Vector2D {
return Vector2D.init(x: 1, y: 1)
}

static postfix func -(right: Vector2D) -> Vector2D {
return Vector2D.init(x: 1, y: 1)
}
}

var v = Vector2D.init(x: 1, y: 1)
let c = v + v
!v
v+=v


// 等价运算符 在类和结构体默认是不支持系统的等价运算符的 ==
// 所以必须要自己重载才可以使用
// 要配合 Equatable 来使用才可以
extension Vector2D: Equatable {
static func ==(right: Vector2D, left: Vector2D) -> Vector2D {
return false
}
}
v==v


// Swift 为自定义的如下类型实现了 == 等价运算符
// 1.遵循了 Equatable 协议,而且只有存储属性结构体
// 1.1 自定义处理的方式
struct Vector2D {
var x = 0.0, y = 0.0
}
extension Vector2D : Equatable {
static func == (left: Vector2D, right: Vector2D) -> Bool {
return false
}
}
Vector2D() == Vector2D()

// 1.2 系统自动实现了 等价运算符
struct Vector3D : Equatable {
var x = 0.0, y = 0.0, z = 0.0
}
Vector3D() == Vector3D()

// 2.遵循了 Equatable 协议,关联类型的enum
// 3.没有关联类型的enum

// 自定义运算符
// 暂时未展开

循环控制 for-in repeat-while

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

// 循环控制 for-in repeat-while
// 遍历序列
for _ in 0...10 {
}
// 遍历数组
for _ in [1,2,3,4,5] {
}
// 遍历字符串
for _ in "abc" {
}
// 遍历字典
for item in [1:1] {
print(item.key)
print(item.value)
}

for (key, v) in ["a" : 1] {
}

for (idx, obj) in [1,2,10].enumerated() {
}

for _ in stride(from: 2, through: 12, by: 2) {}
for _ in stride(from: 2, to: 12, by: 2) {}

repeat {
}while false

while false {
}


// switch swift中switchs默认有 break 功能 而且必须写满全部条件
let c = "a"
switch c {
case "a":
print("a")
case "b":
print("b")
break
default:
print("other")
}

// 复合匹配
switch "a" {
case "a", "A":
print("a A")
default:
print("other")
}

// 区间
switch 1 {
case 0...2:
print("0...3")
default:
print("other")
}

// 元祖处理 (_ 表示此项不比较)
var point = (10,20)
switch point {
case (0,0):
print("(0,0)")
case:(_,0)
print("(_,0)")
case:(0,_)
print("(_,0)")
case:(0...2,0..<100)
print("(_,0)")
default:
print("other")
}

// 还可以临时变量
var point1 = (10,20)
switch point1 {
case (0,0):
print("(0,0)")
case:(let x,0)
print("(_,0)")
case:(0,let y)
print("(_,0)")
case:(0...2,0..<100)
print("(_,0)")
default:
print("other")
}

// 配合 where 来处理 特殊条件

var point3 = (10,20)
switch point3 {
case (x,y) where x == y:
print("x == y")
case:(let x,0)
print("(_,0)")
case:(0,let y)
print("(_,0)")
case:(0...2,0..<100)
print("(_,0)")
default:
print("other")
}

// continue 停止这次循环

// break 结束 for-in while switch 等
// break 在 Swift中是为了理解结束switch 在oc中是为了防止贯穿

// fallthrough 强制到下一个 case,同时下面是否继续贯穿要看下一个 case 是否有 fallthrough

switch 2 {
case 1:
print("1")
fallthrough
case 2:
print("2")
fallthrough
default:
print("other")
}

// 标签
let num = 10
wile : while num > 9 {
switch 1 {
case 1:
print("===1")
// break 强制处理指定标签 强制退出了 少使用为妙。
break wile
fallthrough
default:
print("other1")
}
}

#if if-let guard-else guard-let-else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 1.if
// 2.if-let 在 if 的基础上优化了
// 3.guard-else 不成立就进去,黄金大道。
// 4.guard-let-else 任何一个不成立就进去,黄金大道。

func cc(_ flag: Bool, count: Int?) -> Bool {

do {
let name: String? = "老王"
let age: Int? = 10
if name != nil && age != nil {
print(name! + String(age!)) // 输出:老王10
}
}

do {
let name: String? = "老王"
let age: Int? = 10
// nameNew ageNew 一定是非 nil 的
if let nameNew = name,
let ageNew = age {
// 进入分支后,nameNew 和 ageNew 一定有值
print(nameNew + String(ageNew)) // 输出:老王10
}
}


// 强制类型转换
do{
var name: String? = ""
name = nil
var name1: String? = ""
name1 = nil
if let n = name, let n2 = name1, false == true {
print(n.count + n2.count)
}
if let n = name1 as? Array<Any> {
print(n)
}

guard flag else {
print("fa")
return false
}
}

do {
let name: String? = "老王"
let age: Int? = 10

//
guard let nameNew = name,
let ageNew = age else {
print("姓名 或 年龄 为nil")
return false
}
print(nameNew + String(ageNew)) // 输出:老王10
}

guard let _ = count, count ?? 10>10, flag == false else {
return false
}

return true
}

func cc1(_ flag: Bool, count: Int?) -> Bool {
// 如果不成立就进去。
// 任何一个不成立都进去,如果有nilj也是不成立。
guard let a = count, a > 10, flag == false else {
print("不成立")
return false
}
return true
}

cc1(false, count: nil)
// 在代码上来控制我们尽量使用黄金大道,不满足条件就尽快返回
// Apple 让我们的真正的代码尽量不要写在 if else 中

模式和模式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 模式和模式匹配
// 模式: 是一个值和复合值的结构

// 通配符模式
// _
for _ in 1...100 {
}

// 标识符模式
let A = 100


// 值绑定模式
let po = (10,10)
switch po {
case let (x,y):
print("x - y")
default:
print("default")
}


// 元组模式
let pos = [(1,2),(1,0)]
// 匹配到 y = 0 的元组
for (x,y) in pos where y == 0 {
print("aaa")
}


// enum 模式 参考enum的内容

// 可选值模式 31-xxx

//let someNum: Int = 10
//if case let x? = someNum {
// print("ssss")
//}

// 类型转换模式 31-xxx
// is Dog 遍历多中类型的数组 使用 swiftch 来匹配出具体的类型

// 表达式模式
let po1 = (1,2)
switch po1 {
case (0,0):
print("")
case (1...2,0...2):
print("")
default:
print("")
}
// 可以配合运算符重载来做一些特殊的匹配
struct Employee {
var salaey: Float
}
// 运算符重载
extension Employee {
static func ~=(lhs: Range<Float>, rhs: Employee) -> Bool {
return lhs.contains(rhs.salaey)
}
}
let e = Employee.init(salaey: 100000)
switch e {
case 0..<1000:
print("收入在 0.0...1000")
default:
print("其他")
}

函数 func

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
do {
func greet(_ personName: String) -> String {
return "hi \(personName)"
}
greet("li")
}

do {
func greet(personName: String) -> String {
return "hi \(personName)"
}
greet(personName: "li")

// 隐试返回值
do {
// func fun1(name: String) -> String {
// "a" + name
// }
}

// 默认值
do {
func greet11(personName: String? = "") -> String {
return ""
}
}

// 可变参数个数
do {
//
func greet2222(n: Int?...) -> String {
return ""
}
}
}


// 函数类型
func addTwoNum(_ n1: Int, _ n2: Int) -> Int {
return n1+n2
}
let mathFunc: ((Int, Int)->Int) = addTwoNum

// 函数做为参数来处理
func printMath(_ funccc: (Int,Int)->Int ) {
funccc(1,2)
}
printMath(addTwoNum)

//内嵌函数
do{
func printMath1(_ funccc: (Int,Int)->Int ) -> ((Int,Int)->Int) {
func addTwoNum1111(_ n1: Int, _ n2: Int) -> Int {
return n1+n2
}
return addTwoNum1111
}
}

闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
func paix(n1: Int, n2: Int) ->Bool {
return n1>n2
}

[1,222,3].sorted(by: paix)

// 闭包表达式
// { (n1: Int, n2: Int) -> Bool in
// return false
// }

[1,222,3].sorted (by: { (n1: Int, n2: Int) -> Bool in
return n1>n2
})

[1,222,3].sorted { (n1, n2) -> Bool in
n1>n2
}

[1,222,3].sorted { n1, n2 in
return n1>n2
}

// 单一个表达式 可以直接不加
[1,222,3].sorted { n1, n2 in
n1>n2
}

// $0 第一个参数
[1,222,3].sorted {
$0 > $1
}

// 直接符号
[1,222,3].sorted(by: <)

// 尾随闭包: 如果最后阳光城参数是闭包时,我们可以直接把
// 尾随闭包 把 () 已放弃掉叫尾随闭包
[1,222,3].sorted{$0>$1}

func sorted111(n: Int, by areInIncreasingOrder: (Int, Int) -> Bool) -> [Int] {
return [1]
}

sorted111(n: 10) { (n, n1) -> Bool in
return false
}

sorted111(n: 10, by: { (n, n1) -> Bool in
return false
})

[1].sorted(by: {(n1,n2) -> Bool in
return false
})

// 如何捕获值

// 逃逸闭包: 传给函数的闭包 可能没有在函数中调用,而且其他地方调用,表示这个闭包逃逸了。
// 当func传入的闭包会在func返回后调用时
// 或者传进的闭包会存储到外面的arr中
// 网络请求:函数立即返回 但是 闭包等一下才会真正的调用
do {
func paix(n1: Int, n2: Int) -> Int {
return 1
}

// @escaping
func test(bl: @escaping ((Int, Int)->Int)) -> (Int, Int)->Int {
return bl
}
test(bl: paix);
test(bl: paix)
}

// 逃逸闭包在获取属性的时候需使用 self
class BMPerson {
var x = 10

func testclosure1(closure: @escaping (()->())) -> (()->()) {
return closure
}

func testclosure2(closure: (()->())) {
}

func test1() {
// 逃逸
testclosure1 {
self.x = 10
}
// 非逃逸
testclosure2 {
x = 10
}
}
}


// 自动闭包: 是一种不接受任何参数的闭包,同时他会自动打包表达式,同时返回表达式的值
// 自动闭包可以延时处理

var arr = [1,2]
// 闭包表达式
let c = {
arr.removeAll()
}
print("==")
c()
print("--")


do {
// 闭包表达式
// 定义一个闭包为 c1111
let c1111 = {
(a: Int) -> Int in
print("\(a) + aaaaa")
return a
}
print(c1111(2222))

do {

// 闭包表达式
{
(a: Int) -> Int in
print("\(a) + aaaaa")
return a
}(9999)

}

}


do{
func test1(closure1: @autoclosure ()->Bool) {
}
test1(closure1: 1>1)
}


// 这样的函数的 closure1 满足自动闭包的条件我们尝试使用自动闭包来处理
func test1(closure1: ()->Bool) {
}
test1 { () -> Bool in
return false
}

// 更加简洁
// 自动+逃逸
func test2(closure1: @escaping @autoclosure ()->Bool) -> ()->Bool {
return closure1
}
test2(closure1: arr.count > 10)()

Swift 高阶函数

map filter reduce flatMap compactMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// map
// 对于原始集合里的每一个元素,以一个变换后的元素替换之形成- -个新的集合
print([3].map { (num) -> Int in
return num*num
})

let ccc = [2].map { (num) -> String in
return "\(num)"
}


// filter 条件处理
// 对于原始集合里的每一-个元素,通过判定来将其丢弃或者放进新集合
print(Array(1...20).filter { $0 < 10
// 满足条件的放到新的set中
})

// reduce
// 对于原始集合里的每一个元素,作用于当前累积的结果上
// 累积 累加
// 原始值 count加得到的值 n取到的值
// Result 结果
print(Array(19...20).reduce(10) { (count, n) -> Int in
return count+n
})




// flatMap
// 对于元素是集合的集合,可以得到单级的集合

do {
let arr = [[1,2],[3,4]]

print(arr.flatMap { (nums) -> [Int] in
return nums.map({ (num) -> Int in
return num*10
})
})
// 进一步简化
print(arr.flatMap {$0.map{$0*10}})
}


// compactMap
// 过滤空值
do {

// 如果是非空就加进去
// 这里返回的是 String? 所以是一个 String 数组
print(["a",nil,"aaa"].compactMap { (str) -> String? in
str
})

// 如果是非空就加进去
// 这里返回的是 str?.count 所以是一个Int
print(["a",nil,"aaa"].compactMap { (str) -> Int? in
str?.count
})
print(["a",nil,"aaa"].compactMap { $0?.count})
}

函数式编程

1
2
3
4
具有普遍意义的基本构造单元
●筛选(filter)
●映射(map)
●折叠/化约(foldL eft/reduce等)

enum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
enum ABC : CaseIterable{
case A,B,C
}

let c = ABC.A
switch c {
case .A:
print("a")
case .B:
print("a")
case .C:
print("a")
}

for item in ABC.allCases {
print(item)
}

// 关联值
enum Barcode {
case upc(Int,Int,Int,Int)
case qrCode(String)
}
let code = Barcode.qrCode("ldh")

switch code {
case let .upc(n1, _, _, _):
print(n1)
case .qrCode(let str):
print(str)
}

// 默认值
do {
enum ASci : Character {
case tab1 = "a"
case tab2 = "b"
}
let as1 = ASci.init(rawValue: "a")
print(as1 ?? "aaa")
_ = ASci.tab1
}

// 如果是 Int 或者字符串的时候系统自动设置
enum Planet: Int {
case a = 1,b
}
// a = 1;
// b = 2;


// 默认取名字为它的名字
enum ConPassPoint : String {
case a
}

// 使用 “aaaaaaa” 是无法初始化成功的 所以是 nil
if let aaa = ConPassPoint.init(rawValue: "aaaaaaa") {
print(aaa)
} else {
print("nilll")
}


// 递归enum
// 递归枚举是拥有另一个枚举作为枚举成员关联值的枚举。当编译器操作递归枚举时必须插入间
// 接寻址层。你可以在声明枚举成员之前使用indirect关键字来明确它是递归的。
// 如说表达式(5+4)* 2在乘法右侧有一个数但有其他表达式在乘法的左侧。

//indirect enum Ari thmeticExpression [
//case
//number(Int)
//case
//addition ( ArithmeticExpression, Ari thmeticExpression)
//case multiplication (Ari thme ticExpression,
//Arithmeti cExpression)
//]
//let five = ArithmeticExpression. number(5)
//let four = Arithmetic Expres sion. number(4)
//let sum = Ari thmeticExpression. addition(five, four)
//let product = ArithmeticExpression. multiplication(sum,
//Ari thmeticExpression. number(2))

class 结构体 enum 属性

OOP 面向对象编程

  • 继承
  • 多态
  • 封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 属性
// 存储属性 lazy
// 计算属性
struct Rect {
// var <#variable name#>: <#type#> {
// get {
// <#statements#>
// }
// set {
// <#variable name#> = newValue
// }
// }

// var <#variable name#>: <#type#> {
// <#statements#>
// }

// var <#name#> = <#value#>


// lazy var <#property name#>: <#type name#> = {
// <#statements#>
// return <#value#>
// }()

// lazy var <#variable name#> = <#expression#>
}

// 类型属性
// ●使用static关键字来定义类型属性。
// 对于类类型的计算类型属性,你可以使用class关键字来允许子类重写父类的实现。

struct BMPerson {
var age = 10
static var cla = ""

static var cla1: Int {
get {
return 1
}
set {
}
}
}


class BMPerson1 {
var age = 10
static var cla = ""

class var cla1: Int {
get {
return 1
}
set {
}
}
}

为 class 结构体 enum 添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//// 实例方法
//// 1
//// 在实例方法中、默认可以不写 self
//// 在形参的名字和属性的名字相同的时候需要使用 self 来访问属性
//
//// 2
//// 在实例方法中想修改属性
//// 在值类型【enum 结构体】 属性不可以被自己的实例方法修改
//// 需在方法前面加 mutating mutating func mm(){}
//// mutating 里面可以强制修改 self 属性 self是一个属性 指自己
//// enum 中的 self 可以设置为其他的成员
//
//enum BMType {
// case off,low,height
//
// mutating func next() {
// switch self {
// case .height:
// self = .off
// case .low:
// self = .height
// case .off:
// self = .low
// }
// }
//
// // 如果是 class 的话 而且想在子类中重写这个方法可以把 static 换为 class。
// static func aaa() {
// }
//}
//
//let type1 = BMType.off
//type1.next()
//type1.next()
//BMType.aaa()
//
// // 3 为 class 结构体 enum 提供下标访问 arr[0]
//
////type1["a"]

do{
struct BMTYpe1 {
// subscript(idnex: Int) -> Int {
// return 11122
// }

subscript(index: Int, col: Int) -> Int {
get {
print(111)

return 1
}
set {
print(newValue)
}
}

// Xcode 11
// static subscript(index: Int) -> (Void) {
// get {
// return
// }
// set{
//
// }
// }


}
// var type = BMTYpe1.init()
// print(type[1])
// type[1] = 1
}

类 enum 结构体 的初始化和反初始化

init

deinit

class 继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 便捷初始化器
convenience
// 必须要子类覆盖
required
// 不可以子类覆盖
final
// 此方法是由父类覆盖过来的
override


class Vehicle {
var currentSpeed = 0

final var nnn = 10

var desc: String {
return "run at speed \(currentSpeed)"
}

init(currentSpeed: Int) {
self.currentSpeed = currentSpeed
}
}

class Car: Vehicle {

var gear: Int = 0

// override var nnn: Int {
// get {
// return 1
// }
// set {
// }
// }

override var desc: String {
return super.desc + "\(gear)"
}

init(gear: Int) {
self.gear = gear
super.init(currentSpeed: 10)
}

init(currentSpeed: Int, gear: Int) {
self.gear = gear
super.init(currentSpeed: currentSpeed)
}

convenience init() {
self.init(currentSpeed: 10, gear: 10)
}
}

let c = Car()

协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

protocol VehicleProtocol {
// 属性 可读或者写
var age: Int { get set }
}

// 协议组合,既然遵守协议1 已遵守协议2
VehicleProtocol1 & VehicleProtoco2

// where
// 给 Array 扩展,但前提条件是 Array 中的元素满足给定条件
extension Array: VehicleProtocol where Element: VehicleProtocol {
var age: Int {
get {
return 1
}
set {
}
}
}

//可以给 Collection extension 方法 让所有遵守协议的类型都有了此方法,就可以直接调用了,默认 protocol 是没有方法实现的。
extension Collection {
var age: Int {
get {
return 1
}
set {
}
}
}


// 给 遵守Collection协议的类型一个扩展,但必须满足指定条件,里面的 Element 遵守 VehicleProtocol 协议添加方法
extension Collection where Iterator.Element: VehicleProtocol {
var age111: Int {
get {
return 1
}
set {
}
}
}

let arr = [Vehicle()]
arr.age111

try throw catch

异常处理,比如你封装的一个函数,可能会有异常情况,需要通知外面的使用者,但又不想加参数等,就可以使用 错误处理来实现,当有异常时执行相关的操作。

外面定义一个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 定义函数的时候使用 throws 告诉编译器说这个函数可能会抛出异常
func foo(a: Int) throws -> Int {
if a < -10 {
// 这里需要处理错误
// 需要使用 throw 把错误抛出
// 同时排除的必须是遵守 Error 协议的可以是 enum 结构体 class,通常是 enum 类型
// 我们定义 enum 如下
throw BMError.init()
}
return a
}

/// 定义一个枚举类型的错误类型
enum BMError: Error {
}

// 调用可能抛出异常的函数
// 强制认为不会抛出异常,如果抛出了会崩溃
let ccc = try! foo(a: 10)

// 可以抛出异常,但不处理它
let ccc = try? foo(a: 10)

// 处理异常
// 实现执行 do 中的代码,如果 try (注意没有加?或!) 抛出了异常就跳转到 catch 中
// err 就是抛出的异常信息
// do 中的 try? 和 try! 和外面的 do-catch 没关系
do {
let ccc = try? foo(a: -100)
let ccc = try? foo(a: -100)
let ccc1 = try foo(a: -100)
} catch let err {
}

.Type 、self 、Self、type(of:)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// .Type 是类型的方法 [Int, NSObject], 返回的是此类型属于的类型,不是值。
// Int.Type: 表示 Int 所属的类型。
// NSObject.Type: 表示 NSObject 所属的类型,元类。

// .self可以用在类型后面取得类型本身,也可以用在实例后面取得这个实例本身,返回的是值。
// 1.self 表示 1
// Int.self 表示 Int所属类型的值
// NSObject.self 表示 NSObject的元类的值
// ❌ types.append(Int.Type)
// ✅ types.append(Int.self)


// Self 用在协议中
protocol MProtocolTest01 {
// 协议定一个方法,接受实现该协议的自身类型并返回一个同样的类型
func testMethod(c: Self) -> Self
//不能在协议中定义 范型 进行限制
//Self 不仅指代的是 实现该协议的类型本身,也包括了这个类型的子类
}

class BMPerson: MProtocolTest01 {
func testMethod(c: BMPerson) -> Self {
return self
}
}

// type(of:) vs .self
// 如果我们想获取一个实例的类型类似于 oc 的 class
// self 是返回他自己
// Type 又是类型的方法
// 可以使用 type(of: num) 来获取实例的具体类型
let num: Int = 1
let type1 = type(of: num)
// Int
print(type1)

Any AnyObject AnyClass

1
2
3
// Any       任意类型 enum 结构体 class 元类型都可以
// AnyObject 任意class对象实例 不包括元类型的实例
// AnyClass 任意class类型 不包括元类型

as as? as!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// as
// 子类 -> 父类
// let c2 = BMPPP1() as NSObject

// switch 匹配
// switch animal {
// case let cat as Cat:
// print("如果是Cat类型对象,则做相应处理")
// case let dog as Dog:
// print("如果是Dog类型对象,则做相应处理")
// default: break
// }

// 常量转换
let c = 1 as CGFloat


// as? as!
// 不同的类型转换
// 如果失败的话为 nil ( as! 强制转换,失败就崩溃)

// is
print(1 is Int)
print(NSObject() is NSObject)
- END -
扫一扫上面的二维码图案,加我微信

文章作者:梁大红

特别声明:若无特殊声明均为原创,转载请注明,侵权请联系

版权声明:署名-非商业性使用-禁止演绎 4.0 国际