日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

初探swift语言的学习笔记二(可选类型?和隐式可选类型!)

發布時間:2024/9/30 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 初探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)??
  • ??
  • ????///?Allow?use?in?a?Boolean?context.??
  • ????func?getLogicValue()?->?Bool??
  • ??
  • ????///?Haskell's?fmap,?which?was?mis-named??
  • ????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!)?//?requires?an?exclamation?mark?to?access?its?value??
  • //?prints?"An?optional?string."??
  • ??
  • let?assumedString:?String!?=?"An?implicitly?unwrapped?optional?string."??
  • println(assumedString)?//?no?exclamation?mark?is?needed?to?access?its?value??
  • 實說話,你照這個例子運行,還真看不出什么,得不出什么結論。因此我自己Z磨著,試著理解一個英文翻譯。再自己操刀練習。得出下面的一些結論。

    [cpp]?view plaincopy
  • var?optionVariables:String??//?相當于下面這種寫法的語法糖??
  • //var?optionVariables?:?Optional<Int>??
  • let?value?=?optionVariables?.hashValue??
  • /*?
  • optionVariables是可選類型的字符串,如果optionVariables是nil,則hashValue也為nil?
  • 如果optionVariables不為nil,hashValue就是strValue字符串的哈希值?
  • 到這里我們看到了?的兩種使用場景:?
  • 1.聲明Optional值變量?
  • 2.用在對Optional值操作中,用來判斷是否能響應后面的操作?
  • */??
  • ??
  • //對于可選類型變量,不能直接進行操作,否則會報錯??
  • //let?hashval?=?optionVariables.hashValue?//'String?'?does?not?have?a?member?named?'hashValue'??
  • //因此要訪問值就需要解包,解包有兩種??
  • //第一種:使用if?let/var?xxx?=???
  • if?let?hv?=?optionVariables??
  • {??
  • ????//run?ok;??
  • }??
  • ??
  • //第二種:使用!號??
  • let?hv?=?optionVariables!.hashValue??
  • ??
  • //這里的!表示“我確定這里的的strValue一定是非nil的,盡情調用吧”?,比如這種情況:??
  • ??
  • if?optionVariables?{??
  • ????let?hashv?=?optionVariables!.hashValue??
  • }??
  • //{}里的optionVariables一定是非nil的,所以就能直接加上!,強制拆包(unwrap)并執行后面的操作??


  • 凡在變量或常量后加上?的都是一個可選變量/可選常量
    凡在變量或常量后加上!的都是隱式可選變量/常量,有點難理解,首先該變量或常量滿足可選類型,其主要是可被當生一般的變量/常量來使用,而不需要每次都驗證是否有值。

    注:如果一個隱式解包的可選類型不包含一個實際值,那么對它的訪問會拋出一個運行時錯誤。在變量/常量名后面加!的情況也是一樣的。

    [cpp]?view plaincopy
  • var?possibleString:?String??=?"An?optional?string."??
  • //possibleString?=?nil??
  • println(possibleString)?//?possibleString?為可選變量,需要使用!來訪問的值??
  • 分析:首先 possibleString 因后面帶上了?說明這是一個可選的,同時前面加上var為變量,所以這是一個可選類型的變量。其可選值為 "An optional string." 再來看執行println后,可以看出輸出為 An optional string. 這點很明顯。再來看一下把println這句改一下改為 (即在可選變量后面加上一個!號。)

    [cpp]?view plaincopy
  • <span?style="font-size:18px;">println(possibleString!)?//?possibleString?為可選變量,需要使用!來訪問的值</span>??
  • 這里結果與沒有加!號時是完全一樣的,輸出為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!)?//?possibleString?為可選變量,需要使用!來訪問的值</span>??
  • 這時運行到這句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???????//?默認btn?=?nil??
  • ????????var?btn2?:UIButton?=?UIButton()????//?默認實例化一個對對象??
  • ????????var?btn3?:UIButton!?????//?默認btn?=?nil??
  • ????????//var?btn4?:UIButton????//編譯期報錯?要求進行初始化操作??
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn?=?nil??
  • ????????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)??
  • ??????????
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn3?=?nil??
  • ????????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???????//?默認btn?=?nil??
  • ????????var?btn2?:UIButton?=?UIButton()????//?默認實例化一個對對象??
  • ????????var?btn3?:UIButton!?????//?默認btn?=?nil??
  • ??????????
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn?=?nil??
  • ????????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)??
  • ??????????
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn3?=?nil??
  • ????????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???????//?默認btn?=?nil??
  • ????????var?btn2?:UIButton?=?UIButton()????//?默認實例化一個對對象??
  • ????????var?btn3?:UIButton!?????//?默認btn?=?nil??
  • ??????????
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn?=?nil??
  • ????????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)??
  • ??????????
  • ????????//運行會報錯fatal?error:?Can't?unwrap?Optional.None?因btn3?=?nil??
  • ????????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语言的学习笔记二(可选类型?和隐式可选类型!)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。