Swift switch case编译错误

4
以下代码是从WWDC中间级Swift演讲的示例中推导出来的。我所尝试做的是从某种API获取的键-属性列表初始化一个模型类。
class Movie {
  var title: String

  init(title: String) {
    self.title = title
  }
}

func movieFromDictionary(dict: Dictionary<String, AnyObject>) -> Movie? {
  switch dict["title"] {
  case .Some(let movieTitle as String):
    return Movie(title: movieTitle)
  default:
    return nil
  }
}

当我尝试编译这些代码时,出现如下错误:

Bitcast requires both operands to be pointer or neither
  %38 = bitcast i8* %37 to %SS, !dbg !161
Invalid operand types for ICmp instruction
  %39 = icmp ne %SS %38, null, !dbg !161
PHI nodes must have at least one entry.  If the block is dead, the PHI should be removed!
  %42 = phi i64 , !dbg !161
PHI node operands are not the same type as the result!
  %41 = phi i8* [ %38, %34 ], !dbg !161
LLVM ERROR: Broken function found, compilation aborted!
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 1

有趣的是编辑器似乎对代码没有问题。这是编译器bug还是代码有问题?


2
这肯定是编译器的错误。 - user1804599
1
无论你的代码是否正确,这都是编译器的一个错误。编译器应该能够分析你的代码并决定它是否正确,如果不正确则给出错误,如果正确则生成有效的低级别代码。在这种情况下,它决定它是正确的,然后生成了__无效__的低级别代码,这是绝不应该发生的。你应该向苹果报告这个错误。 - Analog File
3个回答

1

我同意评论者的观点,这是编译器的错误,你应该向苹果报告。但是,你也可以按照以下方式实现,这样更简单,应该能正常工作:

func movieFromDictionary(dict: Dictionary<String, AnyObject>) -> Movie? {
  if let title = dict["title"] as? String {
    return Movie(title: title)
  }
  else {
    return nil
  }
}

你说得对。然而,我实际上是在尝试初始化不止一个字段。所以不仅是“title”属性,还有其他一些属性。尝试在一个switch语句中使用模式匹配来匹配属性要简短得多。但它没有起作用,所以我只使用了一个属性,看看问题出在哪里。 - Haldun

0
我曾经遇到过类似的问题,后来发现如果我先提取我要切换的东西,那么一切都正常了。例如:

而不是

switch segue.sourceViewController {
    case let c as XYZAddToDoItemViewController where c.toDoItem.name.utf16count > 0 :  toDoItems.append(c.toDoItem)
        tableView.reloadData()
    default: println("Unexpected source controller")
}

你应该先声明你要切换的东西(并且它坚持使用AnyObject)

let s:AnyObject = segue.sourceViewController
switch s {
    case let c as XYZAddToDoItemViewController where c.toDoItem.name.utf16count > 0 :  toDoItems.append(c.toDoItem)
        tableView.reloadData()
    default: println("Unexpected source controller")
}

0
switch dict["title"] {
case .Some(let movieTitle as String):

我刚遇到了一个类似的问题,也与字典有关。问题似乎是我所谓的双重转换。dict["title"] 是一个 AnyObject!——也就是说,它是可选的。它被隐式拆包的事实在此时无关紧要。现在你要求将其转换为字符串。因此,你要一次进行两次转换:

  • 你想展开可选项
  • 你想要可选项内部的东西(类型为 AnyObject)可以转换为字符串

正是这种双重转换使编译器产生了麻烦。它应该提供更好的错误信息,而且由于这个问题很容易重现,你应该报告一个 bug。尽管如此,我认为这种双重转换是错误的。你必须分两步进行操作(如上述项目):首先找出 dict["title"] 是否为 nil,然后只有在它不是 nil 的情况下,才解包它并查看是否可以转换为字符串。

情况并没有因为NSDictionary和Dictionary之间的交互不像预期的那样干净利落而变得更好。在我的情况下,事情变得更加复杂,因为这个字典是从用户默认设置中出来的,所以它本身也是可选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接