【发布时间】:2015-06-27 19:56:27
【问题描述】:
Swift 允许我们使用简写符号str! 来解开一个可选项。但是如果我们想反其道而行之呢?
假设我有一个变量:
var str = String() // String
是否有任何简写符号可以将其转换为可选的(即String? 或String!)?
(例如,我想做var strOptional = ?(str)之类的事情。)
或者,如果这个符号没有简写,我如何在不明确提及其类型的情况下将其转换为可选项(例如,我不想提及 String)。
换句话说,我知道我可以使用以下任何方法将变量包装为可选项:
var strOptional = str as String?
var strOptional: String? = str
var strOptional = String?(str)
...但在每种情况下,我都必须明确写成String。
如果没有速记语法,我宁愿写类似:var strOptional = str as typeof?(str)。 (这样做的好处是,如果代码库中变量的类型经常变化,那就少了一个需要更新的地方。)
就这在哪里有用的真实世界示例而言,假设我想使用 AVCaptureDevice 并使用以下代码:
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
device.lockForConfiguration(nil)
lockForConfiguration() 将在运行时在没有摄像机的设备上崩溃,编译器不会警告我。原因是defaultDeviceWithMediaType 根据文档[1] 可能返回nil,但它被定义为返回AVCaptureDevice!。
要修复这样的错误 API,最好执行以下操作:
let device = ?(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo))
...获取AVCaptureDevice?,并让编译器捕捉我可能犯的任何错误。
目前,我必须诉诸更冗长的:
let device: AVCaptureDevice? = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
另一个例子:
在这种情况下,我想给我的变量一个默认值,它是一个字符串,但稍后,我可能想给它分配一个nil 值。
var myString = "Hi"
// ...
if (someCondition()) {
myString = nil // Syntax error: myString is String
}
目前我不得不求助于var myString: String? = "Hi",但像var myString = ?("Hi") 这样的东西会不那么冗长。
[1] 如果您打开 AVCaptureDevice.h,您将看到以下有关返回值的文档:“具有给定媒体类型的默认设备,如果不存在具有该媒体类型的设备,则为零。”
【问题讨论】:
-
嗯,我删除了我的答案。您有足够的代表仍然可以看到它。我的大部分答案仍然适用,但我认为
AVCaptureDevice是一个坚持。当 Apple 首次引入 Swift 时,基本上 everything 返回隐式展开的可选项,但他们应该将所有这些转换为非可选项或常规可选项。这就是 Objective-C 可空性宏的用途。 -
@nhgrif:感谢 cmets。我添加了另一个不涉及 Apple 框架的可能有用的示例。
-
在你的第二个例子中,我认为明确你的类型很重要。 Apple 没有将预处理器宏引入 Swift 是有原因的……
-
我在这两点上都同意@nhgrif。 AVFoundation 还没有被移植。后者显然是
let myString = Optional("Hi")(不过,这不适用于!类型)。如果有人想出一些简单的语法,我不会反对,但我当然不会创建运算符或类似的东西。您可以轻松地将其封装在一个名为lift的函数中,该函数接受一个可选或非可选并返回一个可选。
标签: swift variables syntax casting optional