如何解包返回的字符串:
(可选(可选"蓝"))
GET /intermediate_level/memory_game/play(.:format) intermediate_level/memory_game#play
cityLabelName打印为(可选"纽约")
答案 0 :(得分:95)
给出一个双重可选项,例如这个双重包裹的String
:
let a: String?? = "hello"
print(a as Any) // "Optional(Optional("hello"))\n"
@Leo,showed您可以使用可选绑定两次:
if let temp = a, let value = temp {
print(value) // "hello\n"
}
或强行打开两次:
print(value!!) // don't do this - you're just asking for a crash
以下是另外5种方法可用于安全打开双重选项:
方法1:
您还可以使用模式匹配:
if case let value?? = a {
print(value) // "hello\n"
}
正如@ their answer中提到的@netigger,这也可以写成:
if case .some(.some(let value)) = a {
print(value) // "hello\n"
}
虽然不那么简洁可能会更容易阅读。
方法2:
或者,您可以使用 nil coalescing operator ??
两次:
print((a ?? "") ?? "") // "hello\n"
注意:与此处介绍的其他方法不同,这将始终生成一个值。如果其中一个选项为""
,则会使用String
(空nil
)。
方法3:
或者您可以将 nil coalescing operator ??
与可选绑定一起使用:
if let value = a ?? nil {
print(value) // "hello\n"
}
这是如何运作的?
使用双重包装的可选项,变量保存的值可以是以下三种内容之一:Optional(Optional("some string"))
,Optional(nil)
如果内部可选项为nil
,或nil
如果外部可选项为nil
。所以?? nil
打开外部可选项。如果外部可选项为nil
,则??
会将其替换为默认值nil
。如果a
为Optional(nil)
,那么??
会打开外部可选项nil
。此时,如果内部或外部可选项为String?
,则nil
为nil
。如果内部有String
,则会获得Optional("some string")
。
最后,可选绑定(if let
)解包Optional("some string")
以获取"some string"
或可选绑定如果其中任何一个失败选项为nil
并跳过该区块。
方法4:
此外,您可以将flatMap
与可选绑定一起使用:
if let value = a.flatMap({ $0 }) {
print(value) // "hello\n"
}
方法5:
有条件地将值转换为类型。令人惊讶的是,这将删除所有级别的选项:
let a: String?? = "hello"
let b: String??????? = "bye"
if let value = a as? String {
print(value) // "hello\n"
}
print(b as Any) // "Optional(Optional(Optional(Optional(Optional(Optional(Optional("bye")))))))\n"
if let value = b as? String {
print(value) // "bye\n"
}
答案 1 :(得分:5)
尝试
var a:String?? = "1"
print((a))
if let b = a,c = b{
print(c)
}
游乐场的截图
此外,您可以强行打开包装,但它不安全
let d = a!!
答案 2 :(得分:2)
我必须说接受的答案非常好,我从答案中提出method 1
。但是我想使用不同的语法,使其更具可读性:
if case .some(.some(let value)) = a {
print(value) // "hello\n"
}
答案 3 :(得分:1)
我在reduce()
上做了一个Optional
方法,将Optional(Optional(U))
转换为Optional(U)
(例如Scala中的flatten()
):
extension Optional {
/// - Returns: Given an Optional(Optional(U)) returns an Optional(U)
func reduce<U>() -> U? {
switch self {
case let unwrapped?:
return unwrapped as? U
default:
return .none
}
}
}
要使用它:
字符串示例:
// By using reduce() you directly got a standard optional you can unwrap in the standard way (see answer of @vacawama above).
let aString: String? = Optional(Optional("Hello")).reduce()
let unwrapped = aString ?? "Default"
整数示例:
// By using reduce() you directly got a standard optional you can unwrap in the standard way (see answer of @vacawama above).
let anInt: Int? = Optional(Optional(5)).reduce()
let unwrapped = anInt ?? 10
我主要在需要调用可能引发异常的方法时使用它,但是在当前上下文中我不想捕获该异常。一个示例是读取钥匙串中的用户属性:
let username: String = (try? keychain.get("username")).reduce() ?? "unknown"
答案 4 :(得分:0)
这更是一个重要的评论。
请考虑这样的double可选:
indirect enum S {
case value(s: S?)
case none
}
正常的可选内容如下:
enum S {
case value(s: S)
case none
}
理解为什么在第一个示例中使用indirect
对于所问问题的范围并不重要。没有它就无法编译!在第一个示例中,我只是试图表明其内部类型也是可选类型