2014-06-09 19 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隱式解包的正確應用是不存在的。你的建議將打破使用任何其他隱式解包類型,沒有任何優勢。 –