生活随笔
收集整理的這篇文章主要介紹了
初探swift语言的学习笔记二(可选类型?和隐式可选类型!)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
作者:fengsh998
原文地址:http://blog.csdn.net/fengsh998/article/details/28904115
轉載請注明出處
如果覺得文章對你有所幫助,請通過留言或關注微信公眾帳號 fengsh998 來支持我,謝謝!
可選類型、隱式可選類型
在swift中,可選類型其根源是一個枚舉型,里面有None和Some兩種類型。其實所謂的nil就是Optional.None, 非nil就是Optional.Some, 然后會通過Some(T)包裝(wrap)原始值,這也是為什么在使用Optional的時候要拆包(從enum里取出來原始值)的原因, 也是PlayGround會把Optional值顯示為類似{Some "hello world"}的原因,這里是enum Optional的定義:
[cpp] ?view plaincopy
enum ?Optional<T>?:?LogicValue,?Reflectable?{?? ????case ?None?? ????case ?Some(T)?? ????init()?? ????init(_?some:?T)?? ?? ?????? ????func?getLogicValue()?->?Bool?? ?? ?????? ????func?map<U>(f:?(T)?->?U)?->?U??? ????func?getMirror()?->?Mirror?? }??
語法使用“?” 操作符及"!" 號操作符
如:“var optionalString: String? =? "Hello" optionalString == nil ? var optionalName: String? = "John Appleseed" var greeting = "Hello!" if let name = optionalName { ? ? greeting = "Hello, \(name)" }” 大家把optionalName改為nil時看一下會有什么結果?按照理解,應該是? = 后的為可選值,即當我們的的變量為nil時,這里如果有?=操作,則會使用?=后的值作為默認值,而不會為nil. 這個等有環境時,驗證一下。
經驗證:
分別執行:
[cpp] ?view plaincopy
var?optional?:String??=? "ok?good" ; ?? println(optional)??
輸出為:
ok good
與
[cpp] ?view plaincopy
var?optional?:String? ?? println(optional)??
輸出為:
nil
來看下!號,官方釋為隱式解包:主要用在一個變量/常量在定義瞬間完成之后值一定會存在的情況。這主要用在類的初始化過程中。
官風例子:
[cpp] ?view plaincopy
let?possibleString:?String??=? "An?optional?string." ?? println(possibleString!)??? ?? ?? let?assumedString:?String!?=?"An?implicitly?unwrapped?optional?string." ?? println(assumedString)???
實說話,你照這個例子運行,還真看不出什么,得不出什么結論。因此我自己Z磨著,試著理解一個英文翻譯。再自己操刀練習。得出下面的一些結論。
[cpp] ?view plaincopy
var?optionVariables:String?? ?? ?? let?value?=?optionVariables?.hashValue?? ? ? ? ? ? ? ?? ?? ?? ?? ?? ?? if ?let?hv?=?optionVariables?? {?? ?????? }?? ?? ?? let?hv?=?optionVariables!.hashValue?? ?? ?? ?? if ?optionVariables?{?? ????let?hashv?=?optionVariables!.hashValue?? }?? ??
凡在變量或常量后加上?的都是一個可選變量/可選常量 凡在變量或常量后加上!的都是隱式可選變量/常量,有點難理解,首先該變量或常量滿足可選類型,其主要是可被當生一般的變量/常量來使用,而不需要每次都驗證是否有值。
注:如果一個隱式解包的可選類型不包含一個實際值,那么對它的訪問會拋出一個運行時錯誤。在變量/常量名后面加!的情況也是一樣的。
[cpp] ?view plaincopy
var?possibleString:?String??=? "An?optional?string." ?? ?? println(possibleString)???
分析:首先 possibleString 因后面帶上了?說明這是一個可選的,同時前面加上var為變量,所以這是一個可選類型的變量。其可選值為 "An optional string." 再來看執行println后,可以看出輸出為 An optional string. 這點很明顯。再來看一下把println這句改一下改為 (即在可選變量后面加上一個!號。)
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >println(possibleString!)? ??
這里結果與沒有加!號時是完全一樣的,輸出為An optional string.?
好,現在重點來了,這是很關鍵的一個測試。把possibleString = nil 這句注釋放開讓其動行,再分別來看一下println帶!和不帶!的情況:
情況一:不帶!號時,輸出為nil .
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?possibleString:?String??=? "An?optional?string." ?? ????????possibleString?=?nil?? ????????println(possibleString)?</span>??
情況二:再來看一下帶!號
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?possibleString:?String??=? "An?optional?string." ?? ????????possibleString?=?nil?? ????????println(possibleString!)???
這時運行到這句println就會crash了。會報
fatal error: Can't unwrap Optional.None
錯誤。?
在情況一時,為什么不會報錯,是因為這是一個可選變量當變量為nil時,自動驗證是否有可選的值,有則使用可選值,在情況二,加上!訪問符來訪問possibleString 變量,但由于possibleString設為了nil (等價于var possibleString: String?) 其并沒有包含一個實際值,所以拋異常.同樣對于下面使用!號來聲明的也一樣道:
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?assumedString:?String!?=? "An?implicitly?unwrapped?optional?string." ?? ????????assumedString?=?nil?? ????????println(assumedString!)</span>??
同樣會報:fatal error: Can't unwrap Optional.None
如果你定義了一個可選類型并且沒有給予初始值的時候,會默認設置為nil var surveyAnswer: String? // 初自動設置為nil 注: Swift 的nil不同于Object-C中的nil. Object-C中,nil是一個指針指向不存在的對象。Swift中,nil不是指針而是一個特定類型的空值。任何類型的可選變量都可以被設為nil,不光是指針。
在swift中作何變量/常量的聲明都必須帶有初始值,否則就要聲明為可選型。
即var btn:UIButton 這樣是編譯報錯的。因些必須改為帶初始化的如:
var ?btn2 : UIButton?=? UIButton()
或者使用? 和! 來約束。
因此常常聲明可選或隱式可選變量如:
var btn :UIButton? ? ? ?// 默認btn = nil
var edt :UITextField! ?// 默認edt = nil
至于什么時候使用?什么情況下使用!號來約束變量,我還沒有悟出真真原理。
因此借助于自己的幾次驗證來幫助大家理解。
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?btn??:UIButton??????? ?? ????????var?btn2?:UIButton?=?UIButton()?????? ????????var?btn3?:UIButton!??????? ?????????? ?????????? ????????btn!.tintColor?=?UIColor.blackColor()?? ????????btn!.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????btn!.frame?=?CGRectMake(0,0,50,40)?? ?????????? ?????????? ????????btn2.tintColor?=?UIColor.blackColor()?? ????????btn2.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????btn2.frame?=?CGRectMake(0,0,50,40)?? ?????????? ?????????? ????????btn3.tintColor?=?UIColor.blackColor()?? ????????btn3.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????btn3.frame?=?CGRectMake(0,0,50,40)</span>??
因此為了運行期不crash可以改為如下:
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?btn??:UIButton??????? ?? ????????var?btn2?:UIButton?=?UIButton()?????? ????????var?btn3?:UIButton!??????? ?????????? ?????????? ????????if ?var?tmpbtn?=?btn?? ????????{?? ????????????btn!.tintColor?=?UIColor.blackColor()?? ????????????btn!.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????????btn!.frame?=?CGRectMake(0,0,50,40)?? ????????}?? ?????????? ?????????? ????????btn2.tintColor?=?UIColor.blackColor()?? ????????btn2.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????btn2.frame?=?CGRectMake(0,0,50,40)?? ?????????? ?????????? ????????if ?var?tmpbtn?=?btn?? ????????{?? ????????????btn3.tintColor?=?UIColor.blackColor()?? ????????????btn3.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????????btn3.frame?=?CGRectMake(0,0,50,40)?? ????????}</span>??
或者
[cpp] ?view plaincopy
<span?style= "font-size:18px;" >????????var?btn??:UIButton??????? ?? ????????var?btn2?:UIButton?=?UIButton()?????? ????????var?btn3?:UIButton!??????? ?????????? ?????????? ????????if ?btn?? ????????{?? ????????????btn!.tintColor?=?UIColor.blackColor()?? ????????????btn!.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????????btn!.frame?=?CGRectMake(0,0,50,40)?? ????????}?? ?????????? ?????????? ????????btn2.tintColor?=?UIColor.blackColor()?? ????????btn2.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????btn2.frame?=?CGRectMake(0,0,50,40)?? ?????????? ?????????? ????????if ?btn3?? ????????{?? ????????????btn3.tintColor?=?UIColor.blackColor()?? ????????????btn3.imageEdgeInsets?=?UIEdgeInsets(top:1,left:2,bottom:3,right:4)?? ????????????btn3.frame?=?CGRectMake(0,0,50,40)?? ????????}</span>??
注:如果一個可選類型存在沒有值的可能的話,不應該使用解包(隱式)可選類型。這種情況下,一定要使用正常的可選類型。
這句話我個人是這樣理解的,如var view:UIView。當我的整個應用中或整個類中不可能存在view = nil的情況時可以設置為var view:UIView! 否則就可聲明為var view:UIView?
與50位技術專家面對面 20年技術見證,附贈技術全景圖
總結
以上是生活随笔 為你收集整理的初探swift语言的学习笔记二(可选类型?和隐式可选类型!) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。