Swift 编译器挂起!这是一个错误吗?
Posted
技术标签:
【中文标题】Swift 编译器挂起!这是一个错误吗?【英文标题】:Swift compiler hangs! Is it a bug? 【发布时间】:2014-12-03 00:46:58 【问题描述】:有一次,当我在处理一个 Swift 项目时,Xcode 卡住了状态栏中的“正在编译 Swift 源代码”消息。不管我等了多久,编译都没有完成。我回滚了我最近的更改,并很快意识到让编译器感到困惑的是一个非常简单的枚举构造。下面是一个说明问题的 Playground 示例。
创建一个新的 Playground 并粘贴此代码。看到输出了吗?
// Playground - noun: a place where people can play
import UIKit
enum FastingType: Int
case NoFast=0, Vegetarian, FishAllowed, FastFree, Cheesefare
class Fasting
var allowedFood = [
.NoFast: ["meat", "fish", "milk", "egg", "cupcake"],
.Vegetarian: ["vegetables", "bread", "nuts"],
.FishAllowed: ["fish", "vegetables", "bread", "nuts"],
.FastFree: ["cupcake", "meat", "fish", "cheese"],
.Cheesefare: ["cheese", "cupcake", "milk", "egg"]
]
func getAllowedFood(type: FastingType) -> [String]
return allowedFood[type]
var fasting = Fasting()
println(fasting.getAllowedFood(.Vegetarian))
println("Hello world")
在我的机器上,忙碌指示灯一直在旋转,并且没有消息。我在 Xcode 6.1 (6A1052c) 和 Xcode 6.2-beta (6C86e) 上都试过这个。
这看起来像 Swift 编译器中的错误吗?还是我的代码有问题?
更新:
有几个人注意到我忘记了getAllowedFood
函数中的返回类型。但是,仅此修复程序并不能解决问题。编译器仍然挂起。
在 cmets 中提出了一种解决方法:
Swift 似乎无法解释您的字典。给字典一个明确的类型来“帮助”编译器通常是个好主意。
以下添加“取消冻结”编译器:
var allowedFood: [FastingType: [String]]
【问题讨论】:
bugreport.apple.com 永远不要在操场上测试。 (我知道这就是 Apple 所说的,但不要这样做。)如果您只是在真正的应用程序而不是操场上执行所有这些操作,编译器会为您提供明确的错误消息。 哦,还有一条建议。当然,Swift 或 Cocoa 中可能存在错误,但除非你首先了解当出现问题时,是 你 做错了,否则你不会学习编程。 如果我做错了什么,编译器应该显示错误信息,而不是无限循环! Matt 的建议是务实的,但是是的,编译应该本质上是确定性的,并且永远不要无限循环,即使在操场上也是如此。 【参考方案1】:是的,这可以被认为是编译器错误。编译器无法确定字典中键的类型。可以通过为字典指定显式类型或确保使用 FastingType.NoFast
完全指定第一个值来消除无限循环行为。
试试这个:
enum FastingType: Int
case NoFast=0, Vegetarian, FishAllowed, FastFree, Cheesefare
class Fasting
var allowedFood:[FastingType: [String]] = [
.NoFast: ["meat", "fish", "milk", "egg", "cupcake"],
.Vegetarian: ["vegetables", "bread", "nuts"],
.FishAllowed: ["fish", "vegetables", "bread", "nuts"],
.FastFree: ["cupcake", "meat", "fish", "cheese"],
.Cheesefare: ["cheese", "cupcake", "milk", "egg"]
]
func getAllowedFood(type: FastingType) -> [String]
return allowedFood[type]!
变化:
-
给
allowedFood
类型 [FastingType: [String]]
以便它可以解释您的枚举值。
给getAllowedFood()
一个返回类型。
解开字典查找,因为它们总是返回可选项。
或者,您可以将getAllowedFood()
改为return allowedFood[type] ?? []
,如果您的字典不详尽,这样会更安全。
【讨论】:
或者您可以在 getAllowedFood 中使用 switch 语句来避免!
感谢您“修复”我的代码。不过,我打算问一个不同的问题:为什么原始代码使编译器无限循环?
我猜你绝对可以称之为错误。斯威夫特似乎很难解释你的字典。为字典提供显式类型以“帮助”编译器通常是个好主意。
请注意,只需将 .NoFast
更改为 FastingType.NoFast
即可停止无限循环行为,因为它假定所有其他键也必须为 FastingType
。
谢谢,vacawama!我将您的答案标记为解决方案:-)以上是关于Swift 编译器挂起!这是一个错误吗?的主要内容,如果未能解决你的问题,请参考以下文章