Swift 双重解包可选类型。

9
我理解 Swift 中的可选项,但我刚遇到了“双重可选项”,如果我不使用两个“!”符号,Xcode 将会给出编译器错误提示。

可选类型 'String?' 的值未解包;你是想使用 '!' 还是 '?'?

我有以下代码,其中 app 是类型为 NSRunningApplication 的对象。
let name: String = app.localizedName!

为什么我要使用两个 !?因为这个变量的类型是 var localizedName: String?,一个 ! 不足以将其解包。

上下文: 如果我不使用 let name: String = app.localizedName!!,Xcode 就会报编译器错误。变量 app 的定义如下:

var apps = NSWorkspace().runningApplications.filter{$0.activationPolicy == NSApplicationActivationPolicy.Regular}
for app in apps{
    //code posted above
    …
}

我知道app不是可选项,它总是有一个值,也不是可选应用程序。
附:在使用快速枚举时是否有定义类型的方法?例如:for Foo(app) in apps 其中 apps = [AnyObject]

2
app 到底是如何定义的?它可能是一个可选的 NSRunningApplication 吗? - Martin R
我们正在寻找答案,因为那行代码不应该产生那个错误。如果“app”是可选的,你会得到不同的错误。而且,“localizedName”不是“双重可选项”(哈哈)。这行代码看起来很好,不应该生成那个错误。不幸的是,Swift 可能会生成误导性的错误,我想知道真正的问题是否在之前的某一行代码中(或者你在准备问题时修改或清理了代码行)。此外,当我遇到莫名其妙的错误时,我会清理项目,退出 Xcode,清空派生数据文件夹,并重新启动 Xcode。 - Rob
@MartinR 添加了更多信息。感谢帮助。 - user14492
请查看http://stackoverflow.com/a/28247921/242933。 - ma11hew28
2个回答

4
问题在于NSWorkspace().runningApplications返回的是AnyObject类型的数组,需要将其转换为NSRunningApplication类型的数组:
let apps = NSWorkspace().runningApplications as! [NSRunningApplication]
let filteredApps = apps.filter {
        $0.activationPolicy == NSApplicationActivationPolicy.Regular
}
for app in apps {
    let name: String = app.localizedName!
}

Xcode对上述代码显示错误。您应该将as替换为as!let apps = NSWorkspace().runningApplications as! [NSRunningApplication] - Chris
@Chris:你说得对,这在Swift 1.2(Xcode 6.3)中已经改变了,谢谢你告诉我! - Martin R

2
这是为什么: appAnyObject 类型(Objective-C 中的 id),在 AnyObject 上进行任何查找都会引入一个可选项层,因为方法可能不存在于对象上。 localizedName 本身是可选的,因此您最终会得到两个级别的可选项:如果对象不响应 localizedName,则外部级别为 nil,如果 'localizedName' 为 nil,则内部级别为 nil。

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