为什么';Swift 1.2编译器是否对任何对象强制执行类型检查?

为什么';Swift 1.2编译器是否对任何对象强制执行类型检查?,swift,types,Swift,Types,更新:见下文摘要 我正在努力将程序从Swift 1.1转换为1.2。作为其中的一部分,我遇到了这个(不完美的)代码: 在其他问题中,如果使用参数v调用encode2,则该程序在运行时(毫不奇怪)会崩溃,并出现无法识别的选择器消息。Swift编译器可以通过让我检查它是否是字符串来避免此崩溃,例如: if let v = v as? String { let v2 = v.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncodi

更新:见下文摘要

我正在努力将程序从Swift 1.1转换为1.2。作为其中的一部分,我遇到了这个(不完美的)代码:

在其他问题中,如果使用参数
v
调用
encode2
,则该程序在运行时(毫不奇怪)会崩溃,并出现
无法识别的选择器
消息。Swift编译器可以通过让我检查它是否是字符串来避免此崩溃,例如:

if let v = v as? String {
    let v2 = v.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    ...
}
考虑到Swift 1.2对于让我使用
as是如此挑剔
对于向下播放,我有点惊讶,它没有让我在运行时检查
AnyObject
,或者至少警告我没有这样做

编译器忽略此要求有什么根本原因吗

还是苹果还没有开始做这件事?

在这里和苹果论坛上回答后更新

该策略看起来确实有点奇怪,但与Swift文档一致。如果将变量定义为
AnyObject
,则编译器假定您知道它是危险的。如果您计算的变量是
AnyObject
,编译器会警告您:

但是,如果您对
任何对象
调用一个方法,编译器总是假定您知道自己在做什么,并且什么也不说

“将Swift与Cocoa和Objective C结合使用”一书明确建议在方法名称后面写

if let v2 = v.stringByAddingPercentEscapesUsingEncoding?(NSUTF8StringEncoding) {
     // ...
}
如果方法不存在,则将结果转换为缺少的可选值,而不是崩溃。但是编译器没有强制执行它


对我来说,这似乎很不快捷,但目前是这样。

AnyObject
id
的快速版本,来自:

Swift包括一个名为
AnyObject
的协议类型,它代表任何类型的对象,就像Objective-C中的
id
一样。通过
AnyObject
协议,您可以编写类型安全的Swift代码,同时保持非类型对象的灵活性。由于
AnyObject
协议提供了额外的安全性,Swift将
id
导入为
AnyObject

如果您想要:

您可以利用Swift中的选项从代码中消除此常见的Objective-C错误。在
AnyObject
类型对象上调用Objective-C方法时,该方法调用的行为实际上类似于隐式展开的可选方法您可以使用与协议中可选方法相同的可选链接语法,在任何对象上可选地调用方法

在您的情况下,您可以:

if let v2 = v.stringByAddingPercentEscapesUsingEncoding?(NSUTF8StringEncoding) {
    // ...                                             ^
}
但我也想知道为什么它不是
可选的
,而是
隐含的附加的

在Cocoa API参考中,在API参数中,我们经常看到
错误
任何对象
字符串,等等。。。至于Objective-C互操作,默认值似乎是“隐式展开选项”:

在某些情况下,您可能绝对确定Objective-C方法或属性从不返回
nil
对象引用。为了使此特殊场景中的对象更方便使用,Swift将对象类型作为隐式展开选项导入


也就是说,它是为了“方便”

,因为这就是
任何对象的设计目的

引用(rintaro在回答中引用的部分之后):

您还可以调用任何Objective-C方法并访问任何属性 不强制转换为更具体的类类型。这包括 使用@objc属性标记的Objective-C兼容方法

但是,由于类型为AnyObject的对象的特定类型是 直到运行时才知道,可能会无意中写入不安全的内容 代码。与Objective-C中一样,如果调用方法或访问属性 它不存在于AnyObject类型的对象上,它是一个运行时 错误。例如,以下代码编译时没有投诉,并且 然后在运行时导致无法识别的选择器错误:


我也曾对此感到好奇。在Objective-C中,您可以将任意消息发送到
id
(只要编译器知道签名),但我不明白为什么在Swift中可以这样做。你可以在开发者论坛上提问。谢谢!我在这里贴了一个:实际上我更关心的是对象存在但不是正确类型的情况。你说得对,我可以在函数名后面加一个
,这非常简洁。但我仍然感到惊讶的是,如果我错过了它,编译器并没有警告我。让我们看看是否还有其他人有更好的想法。谢谢rintaro因为他们是第一个而被选中,所以你得到了+1,因为你也很有帮助。谢谢
if let v2 = v.stringByAddingPercentEscapesUsingEncoding?(NSUTF8StringEncoding) {
    // ...                                             ^
}