美文网首页swiftiOS开发常用知识点
swift语言之(可选类型?和隐式可选类型!)

swift语言之(可选类型?和隐式可选类型!)

作者: JaneJie | 来源:发表于2015-08-04 11:35 被阅读2332次

    可选类型、隐式可选类型

    在swift中,可选类型其根源是一个枚举型,里面有None和Some两种类型。其实所谓的nil就是Optional.None, 非nil就是Optional.Some, 然后会通过Some(T)包装(wrap)原始值,这里是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

    来看下官方释为隐式解包:主要用在一个变量/常量在定义瞬间完成之后值一定会存在的情况。这主要用在类的初始化过程中。

    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这句改一下改为 (即在可选变量后面加上一个!号。)

    println(possibleString!) // possibleString 为可选变量,需要使用!来访问的值
    

    这里结果与没有加!号时是完全一样的,输出为An optional string.
    好,现在重点来了,这是很关键的一个测试。把possibleString = nil 这句注释放开让其动行,再分别来看一下println带!和不带!的情况:
    情况一:不带!号时,输出为nil .

      var possibleString: String? = "An optional string."  
            possibleString = nil  
            println(possibleString)  
    

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

      var possibleString: String? = "An optional string."  
            possibleString = nil  
            println(possibleString!) // possibleString 为可选变量,需要使用!来访问的值
    

    这时运行到这句println就会crash了。会报
    fatal error: Can't unwrap Optional.None
    错误。
    在情况一时,为什么不会报错,是因为这是一个可选变量当变量为nil时,自动验证是否有可选的值,有则使用可选值,在情况二,加上!访问符来访问possibleString 变量,但由于possibleString设为了nil (等价于var possibleString: String?) 其并没有包含一个实际值,所以抛异常.同样对于下面使用!号来声明的也一样

    var assumedString: String! = "An implicitly unwrapped optional string."  
            assumedString = nil  
            println(assumedString!)
    

    如果你定义了一个可选类型并且没有给予初始值的时候,会默认设置为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

    相关文章

      网友评论

        本文标题: swift语言之(可选类型?和隐式可选类型!)

        本文链接:https://www.haomeiwen.com/subject/mvmvqttx.html