String
和String!
不完全相同。在這種語言中恰好有足夠的糖來轉換它們。類似地,在語言中有糖可以在String
和String?
之間轉換(但不能反向)。
從基礎開始。有String
。除非有很強的理由,否則當您指的是一串字符時,應該使用String
。其他一切都是「更多的東西」,除非你需要它,否則不應該添加它。
有Optional<String>
。這只是兩種情況,一種具有價值,一個沒有價值的枚舉:
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
// ...
}
沒有爲Optional
後綴運算符!
將返回Wrapped
如果它是可用的,並且崩潰,如果事實並非如此。到目前爲止,沒有魔法。這是你可以建立自己的東西。
在Optional
附近有幾塊魔法。首先,編譯器將Wrapped?
類型神奇地轉換爲Optional<Wrapped>
(對於任何Wrapped
)。這只是句法糖。這兩個符號是相同的。其次,可以選擇與「運營商」鏈接(它不是真正的運營商;它是語言的一部分,您無法自己構建它)。然後有可選的促銷。如果需要,任何類型的Wrapped
都可以自動和隱式轉換爲Wrapped?
。在Optional
之前還有其他一些魔法,比如if-let
的語法,還有nil
這是Optional.None
(我相信它們實際上是相同的)的同義詞。但Optional
真的只是一個通用類型,實現爲枚舉。這只是編譯器知道特殊情況的一種類型。
然後有ImplicitlyUnwrappedOptional<Wrapped>
。這也只是一個枚舉(在Swift 2.2中;這將在Swift 3中改變)。
public enum ImplicitlyUnwrappedOptional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
// ...
}
這是不一樣的Optional
,這是不一樣的Wrapped
。這是完全不同的類型。但它也有一些相關的魔力。首先,類型Wrapped!
是語法糖ImplicitlyUnwrappedOptional<Wrapped>
。再次,它只是糖。兩者是相同的(在Swift 2.2中,不在Swift 3中)。接下來,如果在Wrapped
預計會發現IUO<Wrapped>
,它將自動轉換爲Wrapped
或在沒有值的情況下崩潰。如果在Wrapped?
的地方發現它,它會自動轉換爲Wrapped?
。這些都是神奇的,這就是爲什麼有時String
和String!
似乎是相同的類型。這只是編譯器通過添加一個不可見的轉換步驟而神奇地「爲它工作」。這並不意味着它們真的是同一類型的。
IUO主要用於橋接某些Objective-C模式,特別是涉及故事板,並且應該避免出現這些情況。即使在這些情況下,IUO也只是爲了方便。你可以使用普通的Optionals完成所有相同的事情,你只需要更頻繁地使用if-let
來檢查它們。使用Optionals比使用IUO更安全。很容易想到「我知道這個值在使用之前總會被設置。」就在這個星期,我因爲錯誤而追趕了一個不速之客。 「它應該」和「它一定是」有區別。但是,使用Storyboard中的Optionals完全安全可能會非常不方便,並且可能會掩蓋一些錯誤(不做任何事情而不是崩潰),所以這是IUO最常見的地方。
IUO屬性過去對處理failable init
方法有價值。這在Swift 2.2中不再是問題,因此使用已經消失。我遇到的最後一個「純Swift」用法是當你必須將self
傳遞給你作爲屬性存儲的東西的初始值設定項時(因爲所有的屬性都已經初始化,所以你不能通過self
)。這是一個不幸的用例,非常混亂,我希望我們能爲它提供一個解決方案。在這些情況之外,您應該避免隱式解包選項。
'String'和''字符串不相等本身,他們有一些細微的差別!後者是一個'ImplicitlyUnwrappedOptional'封裝'String',即使它是「隱式解開」,你可以使用例如一個條件綁定塊中的'String!'實例('如果let foo = bar {'''bar'是類型'String!'),而您可能不會用於「純」字符串實例。然而,他們確實有許多相似之處,然而例如安全不是其中之一。 – dfri
@Artyom,根據你的說明,是否最好用'String'類型而不是'String!'聲明'_name',這樣編譯器總是會提醒我在'init'中設置一個值,我的應用程序的崩潰機率會降低,否則,如果像我現在所做的那樣,'_name'是'String!'類型的,我可以得到一個零值並意外崩潰我的應用程序? –
@ Leem.fin你不能初始化你的例子類沒有名字,但你可以設置爲零後名稱,它可以導致崩潰,如果你的變量將被訪問 –