Swift中 !和 ?的區別及使用

2021-07-25 09:59:39 字數 3433 閱讀 6840

相信大家在學習和使用swift的時候,肯定會被!?搞瘋過, 糾結這兩個符號到底是個什麼鬼 ?鬼知道什麼時候使用!,什麼時候使用?

下面就說一下!?區別以及該怎麼使用!

?!其實分別是swift語言中對一種可選型別( optional) 操作的語法糖。 那可選型別是幹什麼的呢? swift中是可以宣告乙個沒有初始值的屬性, swift中引入了可選型別(optional)來解決這一問題。它的定義是通過在型別生命後加加乙個?操作符完成的。

例如:var name: string?

optional其實是個enum,裡面有nonesome兩種型別。其實所謂的nil就是optional.none, 非nil就是optional.some, 然後會通過some(t)包裝(wrap)原始值,這也是為什麼在使用optional的時候要拆包(從enum裡取出來原始值)的原因。

這裡是enum optional的定義

enum optional: logicvalue, reflectable
既然這樣, 那對於var name: string?該怎樣去理解這句語法呢?

var name: string?

// 上面這個optional的宣告,是」我宣告了乙個optional型別值,它可能包含乙個string值,也可能什麼都不包含」,也就是說實際上我們宣告的是optional型別,而不是宣告了乙個string型別 (這其實理解起來挺蛋疼的...)

一旦宣告為optional的,如果不顯式的賦值就會有個預設值nil。判斷乙個optional的值是否有值,可以用if來判斷:

if name
怎麼使用optional值呢?文件中也有提到說,在使用optional值的時候需要在具體的操作,比如呼叫方法、屬性、下標索引等前面需要加上乙個?,如果是nil值,也就是optional.none,會跳過後面的操作不執行,如果有值,就是optional.some,可能就會拆包(unwrap),然後對拆包後的值執行後面的操作,來保證執行這個操作的安全性。

// 例如:

let length = name?.characters.count

ps:對於optional值,不能直接進行操作,否則會報錯。

?的使用場景:

1.宣告optional值變數

2.用在對optional值操作中,用來判斷是否能響應後面的操作

3.使用as?向下轉型(downcast)

上面提到optional值需要拆包(unwrap)後才能得到原來值,然後才能對其操作,那怎麼來拆包呢?

拆包有兩種方法:

// 例子最為簡單明瞭

var str: string? = "hello"

let greeting = "world!"

if let name = str

/**自然語言解釋意思:就是如果str有值,解包它,並且將它的值賦值給name, 然後執行下面的條件語句; 如果str為空, 直接跳過條件語句塊。

*/

var str1: string? = "hello"

let greeting = "world!"

if (str1 != nil)

/**上面例子,我們只是自己知道str1肯定有值, 所以才直接硬解包了str1變數。 但是萬一有時候我們的感覺是錯的, 那程式在執行時可能會出現嚴重的錯誤. 所以swift中是推薦先檢查可選型別是否有值, 然後再進行解包的!

*/

錯誤示範:

var str1:string?    // str1值可能是傳過來的值或者從伺服器獲取的值

let msg = "hi"

let txt = msg + str1! // runtime error

/** 以上**在編譯階段不會報錯.因為使用了硬解包, 編譯器認為可選型別是有值的, 所以編譯是通過的. 當**執行起來時, 知名的錯誤將會出現: `fatal error: can』t unwrap optional.none`

*

ps:對於!操作符,這裡的變數值一定是非nil的!

舉個很淺顯的栗子:

// 在乙個viewcontroller裡面,從xib裡面拖乙個uiimageview控制項, 你會發現xcode會自動給你轉成下面的形式

@iboutlet weak var headerbgimageview: uiimageview!

/***/

ps:如果你在隱式解析可選型別沒有值的時候進行取值,會crash。和在沒有值的可選型別裡面拆包是一樣的。

!的使用場景

1.強制對optional值進行拆包(unwrap)

2.宣告隱式拆包變數,一般用於類中的屬性

其實!?的問題是很坑的,不要看它僅僅是兩個符號,因為只要有乙個不小心,不注意,你會發現專案執行起來,會莫名的crash掉了,關鍵是debug模式也不是很方便定位錯誤型別。 自己整理一下關於 可選型別的相關使用,一是記錄和鞏固所學,而是希望會對大家有所幫助。 本文可能會有錯誤和不妥之處,還望提出,我會及時改正。

Swift中 和 的區別

1.常量和變數 swift語言中是用let來定義常量,並且要初始化。var來定義變數,在let或者var後面申明型別,冒號 空格,然後再加上型別名稱。2.optional 可選 變數 可選變數用於處理值缺失的情況,有點類似於oc中的nil,可以用於任何型別上,不僅僅是類,不過更加安全。swift是型...

php中 和「「的區別及使用

和 通常是php用來定義字串時使用。定義乙個字串最簡單的方法是使用單引號把它包圍起來。在php中想要表達乙個單引號,則需要使用 來進行轉義例 衍生下想要表達乙個 自身則需要使用兩個反斜線。例 在php官方文件中是這樣定義的 不像雙引號和heredoc語法結構,在單引號字串中的變數和特殊字元的轉義序列...

C C 中 和 的使用區別

剛剛,筆者編譯剛寫完的課程實驗時,編譯器報錯200 著實嚇了一跳。仔細一看,基本上全都是類似如下的錯誤提示,這才安心了。遇到這樣的錯誤,其實只需要乙個個把所使用的所有 替換成 運算子即可。不過這也著實浪費了我不少時間去乙個個改誒。qaq 下面,順便來說一下這兩個運算子在使用上的區別 明確一點,是指標...