我很惊讶这个快速的代码表现得很好:
let values = ["Hello", "Test"]
var count = 0
for string: String in values {
count = count + 1
print("count is: ", count)
print(string)
}
输出为:
count is: 1
Hello
count is: 2
Test
但是将String变成String?创建一个无限循环。
let values = ["Hello", "Test"]
var count = 0
for string: String? in values {
count = count + 1
print("count is: ", count)
print(string)
}
输出为:
count is: 1
Optional("Hello")
count is: 2
Optional("Test")
count is: 3
nil
count is: 4
nil
count is: 5
nil
count is: 6
nil
count is: 7
nil
count is: 8
(ad infinitum)
Swift很好地捕捉了奇怪的代码问题,令我惊讶的是,我能在没有警告或错误的情况下陷入混乱。 这真的是人们对Swift 4的期望吗?如果是这样,为什么?
答案 0 :(得分:7)
要了解此问题,有助于重新了解for-in循环的工作方式:
for s in values {
print(s)
}
创建序列的 iterator ,并调用迭代器的next()
方法,直到返回nil
:
var it = values.makeIterator()
while let s = it.next() {
print(s)
}
您的第二个版本等效于
var it = values.makeIterator()
while let s: String? = it.next() {
print(s)
}
现在编译器警告:
warning: explicitly specified type 'String?' adds an additional level of optional to the initializer, making the optional check always succeed while let s: String? = it.next() { ^ ~~~~~~~ ~~~~~~~~~ String
因此,这里发生的是String?
返回的it.next()
被包装到类型为.some(it.next())
的“嵌套可选” String??
中,然后可选地绑定到s: String?
。
因为.some(it.next())
不是String??.none
,所以它总是会成功。
因此循环永远不会终止。
有人可能会认为编译器也应针对
发出警告for s: String? in values {
print(s)
}
答案 1 :(得分:0)
您的“ for”在索引上运行。在索引下,超出元素数的位置为零。
答案 2 :(得分:0)
没有错误。在第一个函数中,它将继续进行直到没有更多的字符串为止。
但是另一方面,第二个函数将字符串设置为可选,因此当不再有字符串时,它仍会继续运行。因为nil是nil值,所以等于零。您没有任何东西可以结束循环。