Swift for循环之坑

630 阅读2分钟

前言

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],完美。( 但是这段代码是有问题的,先暂停思考一下,问题在哪?)

突然有一天,我收到了崩溃信息😭

image.png

经过一番查找,终于定位到了问题,

代码片段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协议的对象,具体的可以查看文档。

一些思考

官网的例子也有一些误导性,比如:

image.png

看了这段代码,power也是变量,官网也没有提示注意崩溃问题。

Swift文档地址

docs.swift.org/swift-book/…