我一直在和Swift 玩,发现当向下投射一个要插入字典的对象时,我会得到一个奇怪的警告:Treating a forced downcast to 'String' as optional will never produce 'nil'.如果我把as换成as?,警告就会消失.

func test() -> AnyObject! {
  return "Hi!"
}

var dict = Dictionary<String,String>()
dict["test"]=test() as String

苹果的文件中说:

因为向下转换可能会失败,所以类型转换操作符有两种不同的形式.可选表单as?返回一个可选值,该值是您试图向下转换到的类型.强制形式astry 向下投射,并将结果作为单个复合动作展开.

我不清楚为什么这里用as?而不是as是正确的.一些测试显示,如果我将test()更改为返回一个Int而不是字符串,那么如果我继续使用as,代码将因错误而退出.如果我切换到使用as?,那么代码将继续正常执行,并跳过该语句(dict将保持为空).然而,我不确定这为什么更可取.在我看来,我宁愿程序错误退出,让我知道演员阵容不成功,然后干脆忽略错误语句并继续执行.

根据文档,我应该使用强制形式"只有当你确信沮丧总是会成功的时候"在这种情况下,我确信向下投射总是会成功的,因为我知道test()只能返回一个字符串,所以我认为这是强制向下投射的完美情况.那么为什么编译器会给我一个警告呢?

推荐答案

让我们仔细看看你的最后一行,然后爆炸,看看发生了什么:

let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString

错误出现在第二行,您告诉编译器强制执行temporaryAnyObject肯定是String.代码仍将编译(假设您不将警告视为错误),但如果temporaryAnyObject实际上不是String,代码将崩溃.

as的工作方式,而不是?,基本上是说"从现在开始,如果结果实际上是那种类型的,就把这个表达式的结果当作那种类型,否则我们就变得不一致,不能再运行了.".

as?的工作方式(与?一起)是这样的:"从现在开始,如果结果实际上是该类型的,则将此表达式的结果视为该类型,否则此表达式的结果为nil.

在我上面的分解示例中,如果test()返回String,那么as向下转换成功,temporaryString现在是String.如果test()不返回String,而是说Int或其他任何未从字符串中子类化的内容,那么as将失败,代码将无法继续运行.

这是因为,作为完全控制的开发人员,您告诉系统不要放置可选的?指示器,这样做.as命令特别意味着你不能容忍任性行为,你需要这种沮丧情绪才能发挥作用.

如果您输入了?,那么temporaryString将是nil,第三行将简单地从字典中删除"test"键/值对.

这可能看起来很奇怪,但这只是因为这与许多语言的默认行为相反,比如Obj-C,默认情况下,它将所有内容都视为可选的,并依赖于您自己进行判断和断言.

Edit - Swift 2 Update

自Swift 2以来,强制的、可故障的下行操作符as已被移除,并被更快速的as!替换.行为是一样的.

Swift相关问答推荐

如何使用RxSwift根据数据数绘制UICollectionView单元格

RxSwift .debounce,.throttle用于分页

background Task(.backgroundTask)不适用于MySQL

同时具有每个文本的标识符的文本组的可扩展性标识符

解码器是否需要具有密钥的外部数据表示?

在Swift中如何将NSUrl转换为本地路径URL

当字符串包含 \r\n 时,NSRegularExpression 不起作用

如何在一个视图控制器中创建具有相同行为的多个集合视图?

为 SwiftUI 中的属性提供默认值

关于变量的视图的 SwiftUI 生命周期

SwiftUI:决定键盘重叠的内容

如何有条件地依赖桌面与 iOS 的系统库?

来自数据的 SwiftUI 图像

判断 Swift 程序是否正在输出到终端

组合 flatMap 不会返回预期的上下文结果类型

如何在不阻塞 UI 更新的情况下使用 Swift Concurrency 在后台执行 CPU 密集型任务?

Swift 函数 vs 惰性变量 vs 计算(computed)属性 - 区别?

try 在解除分配时加载视图控制器的视图... UIAlertController

Void 函数中意外的非 Void 返回值 (Swift 2.0)

如何使用 Swift 将文本文件逐行加载到数组中?