【问题标题】:For-in loop goes one-too-far and finds 'nil' while unwrappingFor-in 循环走得太远,在展开时发现“nil”
【发布时间】:2016-07-15 02:23:14
【问题描述】:

看起来下面的 Swift for-in 循环试图遍历比数组中更多的元素。

例如,这段代码:

var list:[Int?] = [1,2,3,4,5,6,7]

print("C-Style for loop")
for var i=0; i<list.count; i++ 
{
    var x:Int = list[i]!
    print(x)
}

print("\nFor-in loop")
for var x:Int! in list
{
    print(x)
}

得到这个输出:

C-Style for loop
1
2
3
4
5
6
7

For each loop
1
2
3
4
5
6
7
fatal error: unexpectedly found nil while unwrapping an Optional value
... 
Illegal instruction: 4

我一定在这里遗漏了什么。 list.count 不应该是 for-in 循环尝试解包的元素数吗?

如上图所示,如果使用 [Int] 列表而不是 [Int?] 且没有展开,for-in 循环将按预期工作。

我使用的是 Swift 2.1.1 版。

【问题讨论】:

  • 这里有一些奇怪的行为。如果将list 标记为[Int],然后将x 标记为Int?,则for-in 循环将永远打印nil
  • @Robert 如果您了解它的工作原理,这种行为并不是特别奇怪......但 Swift 可能应该简单地阻止 x 被标记为这样的可选标签(因为它只能导致无限循环)。
  • 你能简单解释一下发生了什么吗?为什么会造成无限循环?
  • @Robert 我对你刚才提出的问题的回答并没有完全涵盖那个解释,但我愿意回答你的问题......但在 cmets 中这样做会有点困难。也许通过here 的解释,你有足够的信息来弄清楚。

标签: swift for-loop for-in-loop


【解决方案1】:

基本上你做了一些你不应该做的事情,因此你偶然发现了一些可能是编译器错误的事情(因为编译器没有阻止你)。很不错!

现在解决方案。您显然正试图用您的Int! 解开包装。要安全地展开,请使用for case 语法:

let list:[Int?] = [1,2,3,4,5,6,7]
for case let x? in list
{
    print(x) // 1, 2, 3, 4, 5, 6, 7
}

另一种方式(结果相同):

let list:[Int?] = [1,2,3,4,5,6,7]
list.flatMap{$0}.forEach{print($0)} // 1, 2, 3, 4, 5, 6, 7

【讨论】:

  • 所以 forEach 也遇到了同样的问题...可怕。
  • @Darko 不,实际上不是;这给了我另一种解决方案——简单的list.forEach{print($0!)} 有效(当然,由于其他原因它可能很危险)
  • 是的,但是 list.forEach{print($0)} 也会崩溃。这里对 flatMap 的需求让我感到害怕。
  • case let x? in list 中的那个问号实在是太不直观了。我不知道在 Swift 的其他任何地方我们都可以这样展开。
  • 我也认为(same result) 至少有点误导。 Playground 建议您答案底部的替代解决方案要贵得多:i.stack.imgur.com/QB8zN.png(对于具有 13 个元素的数组,6 nil)。
【解决方案2】:

当你不能排除 nil 时,像 x:Int! 这样的强制展开是一种危险的编码风格。 var x:Int = list[i]! 也是如此。

这行得通:

print("\nFor-in loop")
for x in list {
   print(x)
}

在这里您允许 x 为 nil,以后可以安全地检查 nil。

现在来回答为什么你的代码会中断的问题:

在内部,swift 使用 list.generate() 进行 for-in 循环。生成器是 nil 终止的,这可能是您的代码中断的原因。

【讨论】:

  • 但问题是这会产生 Optional(1)、Optional(2) 等,这不是 OP 想要的。
  • 你是对的。我怀疑 print 仅用于调试,而 OP 显然知道如何解包。对我来说更有趣的问题是它为什么会失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 2015-04-27
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
相关资源
最近更新 更多