如何打开双重选项?

时间:2015-10-10 01:17:34

标签: swift

如何解包返回的字符串:

(可选(可选"蓝"))

GET    /intermediate_level/memory_game/play(.:format)     intermediate_level/memory_game#play

cityLabelName打印为(可选"纽约")

5 个答案:

答案 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。如果aOptional(nil),那么??会打开外部可选项nil。此时,如果内部或外部可选项为String?,则nilnil。如果内部有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)
}

游乐场的截图

enter image description here

此外,您可以强行打开包装,但它不安全

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对于所问问题的范围并不重要。没有它就无法编译!在第一个示例中,我只是试图表明其内部类型也是可选类型