前言
for循环在我们的日常开发过程中扮演者重要的角色,我们经常需要遍历处理数据,在swift中使用for循环也非常的方便。但是for循环有一些坑,本篇文章就来通过一些列子梳理一下这些坑。
数组遍历问题
代码片段1
var arr = [1,2,3,4,5]
for value in arr {
debugPrint(value)
}
循环打印数组元素,这段代码有啥问题吗? 没有问题。 接下来,我想把数组中每个值都加1
代码片段2
var arr = [1,2,3,4,5]
for var value in arr {
value += 1
}
debugPrint(arr)
能实现我们想要效果吗? 答案是不能,因为Int是值类型,存在写时复制。换一种方式:
代码片段3
var arr = [1,2,3,4,5]
for i in 0..<arr.count {
arr[i] += 1
}
debugPrint(arr)
打印结果[2, 3, 4, 5, 6],不错,完美实现我们想要的。 突然有一天,需求变化了,要求从数组第三个元素开始+1,头两个不变,如果不足三个则不用+1.
这个需求很简单,看我操作:
代码片段4
var arr = [1,2,3,4,5]
for i in 2..<arr.count {
arr[i] += 1
}
debugPrint(arr)
打印结果[1, 2, 4, 5, 6],完美。( 但是这段代码是有问题的,先暂停思考一下,问题在哪?)
突然有一天,我收到了崩溃信息😭
经过一番查找,终于定位到了问题,
代码片段5
var arr = [1]
//arr.count 不能比2小, WTF
for i in 2..<arr.count {
arr[i] += 1
}
debugPrint(arr)
..< 是swift的一种Range操作符,感兴趣的这里是传送门.
这对于习惯了for(int i =0 ; i < arr.count ;i++) 的我来说有点不能接受。
解决也比较好办,加一个判断 if arr.count < 2 { return } 但是这不是优雅的方案。
解决方案
通过阅读官网语言指导,发现了解决之道。
var arr = [1]
for i in stride(from: 2, to: arr.count, by: 1) {
arr[i] += 1
}
debugPrint(arr)
打印结果:[1], ✅
stride 函数返回的是实现了Strideable协议的对象,具体的可以查看文档。
一些思考
官网的例子也有一些误导性,比如:
看了这段代码,power也是变量,官网也没有提示注意崩溃问题。