Swift 不可能的类型推断

Swift Impossible Type Inference

我试图从 Swift 3 中的应用程序包中加载一个文件,但我遇到了 Swift 类型推断的奇怪情况。如果我使用下面的代码,我会在第三行收到一个错误 Value of optional type "String?" not unwrapped.

let url = NSURL(fileURLWithPath:Bundle.main.bundlePath)
let url2 = url.appendingPathComponent("foo.txt")
let path:String = url2?.path

为了修复错误,我将第三行的值更改为:

let path:String = url2?.path!

我现在收到错误 Cannot force unwrap value of a non-optional type 'String'。似乎 Swift 无法确定路径 属性 是 String 还是 String?。 Xcode 中的自动完成功能说它是 String,但文档说它是 String?

Xcode 对第一个错误的建议修复是将 url2?.path 替换为 (url2?.path)!,这最终奏效了,但我不知道为什么会这样和另一个方法不。

let path:String = (url2?.path)!

这是怎么回事?这是 Swift 中的类型推断错误,还是我遗漏了一些非常明显的东西

你忘了打开包装url2

appendingPathComponent returns 一个可选值,您正试图在不打开它的情况下访问它。

所以,

let url2 = url.appendingPathComponent("foo.txt")!

guard let url2 = url.appendingPathComponent("foo.txt") else { }

应该修复它

编辑

let path:String? = url2?.path

也适用

在 Swift 中,可选链接如:

let path:String = url2?.path!

... 解释为:

let path:String = url2 != nil ? url2!.path!
                              : nil

如您所见,path 的类型是非可选的 String,因此表达式会导致错误。

url2的类型是URL?,所以属性path的类型是String,不是String?。)


这不是您问题的直接答案,但我会将您的代码重写为:

let url = Bundle.main.bundleURL
let url2 = url.appendingPathComponent("foo.txt")
let path:String = url2.path

更短,不用担心 Optionals。

您也可以这样做:

let url = Bundle.main.url(forResource: "foo", withExtension: "txt")!
let path:String = url.path