Swift 如何展开双选项?
如何打开返回为以下格式的字符串: (可选(可选“蓝色”)) cityLabelName打印为Swift 如何展开双选项?,swift,Swift,如何打开返回为以下格式的字符串: (可选(可选“蓝色”)) cityLabelName打印为(可选“纽约”)试试 var a:String?? = "1" print((a)) if let b = a,c = b{ print(c) } 游乐场截图 也可以强制展开,但它不安全 let d = a!! 给定一个双可选项,例如双包装的字符串: let a: String?? = "hello" print(a as Any) // "Optional(Optional("hello"
(可选“纽约”)
试试
var a:String?? = "1"
print((a))
if let b = a,c = b{
print(c)
}
游乐场截图
也可以强制展开,但它不安全
let d = a!!
给定一个双可选项,例如双包装的
字符串
:
let a: String?? = "hello"
print(a as Any) // "Optional(Optional("hello"))\n"
@Leo,您可以使用可选绑定两次:
或强制展开两次:
print(value!!) // don't do this - you're just asking for a crash
您还可以使用以下5种方法安全地展开双面打印: 方法1: 您还可以使用模式匹配: 正如@netigger在中所指出的,这也可以写成:
if case .some(.some(let value)) = a {
print(value) // "hello\n"
}
虽然不那么简洁,但可能更容易阅读
方法2: 或者,您可以使用零合并运算符两次:
print((a ?? "") ?? "") // "hello\n"
注意:与此处介绍的其他方法不同,这将始终产生一个值<如果任一选项为nil
,则使用“(空字符串
)
方法3: 或者,您可以使用带有可选绑定的nil合并运算符
??
:
这是如何工作的?
对于双重包装的可选变量,变量所持有的值可以是以下三项之一:可选(可选(“某些字符串”))
,可选(nil)
(如果内部可选是nil
),或者nil
(如果外部可选是nil
)。那么一个??无
打开外部可选组件。如果外部可选值为nil
,则?
将其替换为默认值nil
。如果a
为Optional(nil)
,则??
将打开外部可选的nil
。此时,如果内部或外部可选项为nil
,则将有一个字符串?
,即nil
。如果里面有一个字符串
,您将得到可选(“某些字符串”)
最后,可选绑定(
if let
)打开optional(“some string”)
以获取“some string”
,或者如果其中一个选项为nil
并跳过该块,则可选绑定失败
方法4: 此外,您还可以使用带有可选绑定的
flatMap
:
方法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
。但是,我想使用不同的语法,使其更具可读性:
if case .some(.some(let value)) = a {
print(value) // "hello\n"
}
我在Optional
上做了一个reduce()
方法,将可选(可选(U))
转换为可选(U)
(如Scala中的展平()
):
Int示例:
// 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"
这是一个更重要的评论
将双选项视为:
indirect enum S {
case value(s: S?)
case none
}
而普通的可选选项如下所示:
enum S {
case value(s: S)
case none
}
理解在第一个示例中使用的原因对于所问问题的范围并不重要。没有它就无法编译!在第一个例子中,我只是想说明它的内部类型也是一个可选的类型the
??零
太棒了!这是最好的答案,尤其是方法3。@Raginmari,对于双包装可选变量,变量所持有的值可以是三件事之一:可选(可选(“某些字符串”)
,可选(nil)
如果内部可选是nil
,或者nil
如果外部可选是nil
。所以a??无
打开外部可选组件。如果外部可选设置为nil
,则??将其替换为默认值nil
。如果a
为可选(无)
,则??将打开外包装,留下nil
。此时,如果内部或外部可选项为nil
,则得到nil
。如果里面有一个字符串,您将得到可选(“某些字符串”)
。最后,可选绑定将打开可选(“某些字符串”)
,以获得“某些字符串”
,或者如果其中一个选项为nil
,则它将失败。方法1和3是我读过的关于该案例的最佳代码片段。谢谢你这么好的帖子!
if case .some(.some(let value)) = a {
print(value) // "hello\n"
}
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"
indirect enum S {
case value(s: S?)
case none
}
enum S {
case value(s: S)
case none
}