zoukankan      html  css  js  c++  java
  • 初步swift语言学习笔记2(可选类型?和隐式可选类型!)

    作者: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的定义:

    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. 这个等有环境时,验证一下。

    经验证:

    分别执行:

            var optional :String?

    = "ok good";//注意?与=号之间有空格?号紧贴最后一个字母不能有空格 println(optional)

    输出为:

    ok good

            var optional :String?//注意?与=号之间有空格?

    号紧贴最后一个字母不能有空格 println(optional)


    输出为:

    nil


    来看下。号,官方释为隐式解包:主要用在一个变量/常量在定义瞬间完毕之后值一定会存在的情况。

    这主要用在类的初始化过程中。

    官风样例:

    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磨着,试着理解一个英文翻译。再自己操刀练习。

    得出以下的一些结论。

            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)并执行后面的操作



    凡在变量或常量后加上?

    的都是一个可选变量/可选常量
    凡在变量或常量后加上!的都是隐式可选变量/常量,有点难理解,首先该变量或常量满足可选类型。其主要是可被当生一般的变量/常量来使用,而不须要每次都验证是否有值。

    注:假设一个隐式解包的可选类型不包括一个实际值,那么对它的訪问会抛出一个执行时错误。在变量/常量名后面加!

    的情况也是一样的。

            var possibleString: String?

    = "An optional string." //possibleString = nil println(possibleString) // possibleString 为可选变量。须要使用!来訪问的值

    分析:首先 possibleString 因后面带上了?说明这是一个可选的。同一时候前面加上var为变量,所以这是一个可选类型的变量。其可选值为 "An optional string." 再来看执行println后,能够看出输出为 An optional string. 这点非常明显。再来看一下把println这句改一下改为 (即在可选变量后面加上一个!号。)

    <span style="font-size:18px;">println(possibleString!) // possibleString 为可选变量,须要使用!来訪问的值</span>
    这里结果与没有加!号时是全然一样的。输出为An optional string. 

    好,如今重点来了,这是非常关键的一个測试。把possibleString = nil 这句凝视放开让其动行,再分别来看一下println带!和不带!的情况:

    情况一:不带!号时。输出为nil .

    <span style="font-size:18px;">        var possibleString: String?

    = "An optional string." possibleString = nil println(possibleString) </span>

    情况二:再来看一下带!号

    <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?) 其并没有包括一个实际值,所以抛异常.相同对于以下使用!号来声明的也一样道:

    <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

    至于什么时候使用?

    什么情况下使用!号来约束变量,我还没有悟出真真原理。

    因此借助于自己的几次验证来帮助大家理解。

    <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能够改为例如以下:

    <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>

    或者

    <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?



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    C#编写最小花时隐藏为任务栏图标的Window appllication
    XML与HTML的结合
    敏捷思维-架构设计中的方法学(1)从方法论看架构设计
    敏捷思维-架构设计中的方法学(4)团队设计
    敏捷思维-架构设计中的方法学(2)架构设计的敏捷视图
    敏捷思维-架构设计中的方法学(5)简单设计
    hdu 1116(并查集+欧拉路判断)
    hdu 2145(最短路+排序)
    hdu 2377
    hdu 2962(最短路+二分)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4776766.html
Copyright © 2011-2022 走看看