2014-06-09 17 views
9

一个布尔类型的隐含解缠的隐含解缠似乎不工作:一个可选的布尔

var aBoolean: Bool! // nil 
aBoolean = false  // false 
aBoolean    // false 

aBoolean == true  // false 
aBoolean == false  // true 

if aBoolean { 
    "Hum..."   // "Hum..." 
} else { 
    "Normal" 
} 

if aBoolean! { 
    "Hum..." 
} else { 
    "Normal"   // "Normal" 
} 

如果我宣布aBooleanvar aBoolean: Bool?,这将是预期的行为,但在这里,我不没办法。

这是正确的行为吗?我没有找到任何关于它的文档。

谢谢!

+1

我很高兴输入'if!bool! ......“有一天! – GoZoner

+1

^这就是我想到的!哈 – Dash

+0

该代码不会编译。你错过了大括号。 – matt

回答

8

第一个测试是检查是否aBoolean存储值而不是零,这它的作用:

if aBoolean { 
    "Hum..."   // "Hum..." 
else { 
    "Normal" 
} 

第二测试是检查与存储在aBoolean实际布尔值,它是假:

if aBoolean! { 
    "Hum..." 
} else { 
    "Normal"   // "Normal" 
} 

这是在“隐式包装的选项”部分中的Swift书中说明的。我认为隐含的解包不适用于if语句。我同意这是奇怪的,但这里是苹果的例子:

,您仍然可以把一个隐含展开可选像一个正常的可选,以检查其中是否包含一个值:

let assumedString: String! = "An implicitly unwrapped optional string." 

if assumedString { 
    println(assumedString) 
} 
// prints "An implicitly unwrapped optional string." 

摘自:苹果公司“Swift编程语言”,iBooks。 https://itun.es/us/jEUH0.l

+1

是的,但问题是他为什么需要打开布尔值,如果布尔值被声明为“隐式地解开”使用感叹号 –

+0

@Dash请参阅上面的评论 – Damien

+0

知道了..更新! – Dash

0

当变量声明为“隐含地解开”,利用!,它仍然是一个Optional

这种类型的变量的行为非常象在Objective-C的标准可变类型。它可以被分配到nil,但是当你访问成员时,你不需要明确地解开它。就像在ObjC中一样,它是“不安全的”,因为您可以从零访问属性

因此,它在Objective-C桥接时最常用。但是,它仍然是可选的,唯一的区别是你不需要打开它来访问内容。

我认为这主要是为了支持Swift和Obj-C之间的互操作,并且可能是在纯Swift代码中谨慎使用它的好实践。 (斯威夫特的指导方针现在是一件模糊的事情,有人可能会很快证明我错了!)

+0

在纯粹的swift中,它们对于IBOutlets很有用。这些都是零,直到笔尖被加载,但从那时起,他们有一个价值。每次检查值都会很乏味。但是在这里他们被用于可可物体,所以Bool混乱!不是问题。 –

+0

@SteveWaddicor伟大的一点!我相信'IBOutlets'在默认情况下是隐式的解包选项,所以你实际上不需要'!'语法。 – Jack

2

你正在做两个不同的事实检查。

考虑:

var aBoolean: Bool! // nil 
aBoolean = false  // false 

if aBoolean { 
    "Hum..."   // "Hum..." 
else { 
    "Normal" 
} 

if aBoolean! { 
    "Hum..." 
} else { 
    "Normal"   // "Normal" 
} 

...在第一if aBoolean,价值没有被解开,它只是测试可选类型,以确定它是否的值。

在第二个if aBoolean!中,您正在测试展开Bool的真值。

地看到,它确实是隐式展开的(当在条件未使用),请尝试:

println("value of implicitly-unwrapped aBoolean: \(aBoolean)")

...当aBoolean设置为会打印出“真” true,当它被设置为false时为'false',当它尚未被分配时为'nil'。

1

这里是清楚地示出的行为:

> var bool1 : Bool! 
bool1: Bool! = nil 
> bool1 = false 
> (bool1 ? "yes" : "no") 
$R19: (String) = "yes" 

在上文中,因为bool1可选(其变为Some实例)中,条件的简单bool1评估为true(它不是nil )。

> var bool2 : Bool = false 
bool2: Bool = false 
> (bool2 ? "yes" : "no") 
$R25: (String) = "no" 

bool2不是可选,有条件的干脆bool2计算为false(的bool2值)

6

不是一个答案,但如果这确实是有隐含展开布尔预期的行为这很令人不安。只要你使用任何逻辑命题表达它会得到展开:

var aBoolean: Bool! = false 

if !aBoolean { 
    "I'm unwrapping"   // "I'm unwrapping" 
} 

if aBoolean == false { 
    "I'm unwrapping"   // "I'm unwrapping" 
} 

你在你的代码在某些时候你的模型变化和条件被反转都这样了,你删除了不。

if aBoolean { 
    "I'm unwrapping"   // <- ouch 
} 

你刚刚搞砸了。使我想避免隐含的解包。

+0

通常你应该避免隐式展开。它的动机是'IBOutlets'等案例。在这里你有一个类,其成员变量在init()完成后仍然为零,但在加载nib时分配了一个值。所以从'awakeFromNib()'开始之前,它们将永远不会有零值,并且所有的解包都是毫无意义的。这些东西是可可物体而不是布尔物体,所以你提出的问题不适用。 可能有其他类似的情况下使用隐式展开。但对于一般用途,您应该使用普通条件。 –

+0

我不认为隐式展开的正确应用是稀缺的。我所说的是我认为一个更好的实现将会是这样做,除非你明确地尝试用“if let”来展开它...... –

+0

对于Bool隐式解包的正确应用是不存在的。你的建议将打破使用任何其他隐式解包类型,没有任何优势。 –