Swift中的感叹号( ! )与问号( ? )之谜

Swfit4.0 学习 2019-05-06 已阅 653 次

基本了解

在Swift代码会经常看到定义属性或方法参数时类型后面会紧跟一个感叹号( ! )或问号( ? ), 刚开始接触Swift的童鞋就可能不太明白之代表什么意思,一头雾水,开始凌乱了。
本文将带你了解感叹号( ! )与问号( ? )之谜,首先问号( ? )是可选类型,是用来处理值可能缺失的情况,也就是没有值的情况(也就是OC中NULL); 感叹号( ! )就是与之相反的, 就是一定有值(非可选类型),不存在空值的情况(OC中NULL)。
下面根据不同使用场景来进一步了解感叹号( ! )与问号( ? )之谜

各个场景中的叹号( ! )与问号( ? )

类的属性

class MyClass {
    
    var value: String!
    var optionalValue: String? // defaulit is nil, 所有定义为可选类型的,可选值都是nil, 和数据类型没有关系。
 }
MyClass定义了2个属性:valueoptionalValue,其中optionalValue为可选类型;这表示value在使用之前一定是赋了值的(一定有值),optionalValue则有可能值缺失。下面先来看看几个代码片段来深入了解感叹号( ! )与问号( ? )之谜

1. 下面代码,在运行时初始化一个MyClass实例会发生什么呢?

class MyClass {
    
    var value: String!
    var optionalValue: String?
    
    init() {
        
        let _ = value.count
        let _ = optionalValue?.count // 可选解析
    }
}

程序会崩溃,报以下错误
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

value是非可选类型,必须要有值,从代码中看出value从赋值过。另外构造函数里的问号( ? )是指可选解析(弱解析),并不是指可选类型,这里要注意了

2. 下面代码,在运行时初始化一个MyClass实例会发生什么呢?

class MyClass {
    
    var value: String!
    var optionalValue: String?
    
    init() {
        
        value = "this is string value."

        let _ = value.count
        let _ = optionalValue!.count // 强解析
    }
}

程序会崩溃,和代码片段1报一样的错误
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

大家肯定奇怪了明明value已经赋值了,为什么还会崩溃,问题出在optionalValue属性,不知道大家注意了没有,此代码的构造函数中optionalValue后面是感叹号( ! ),而代码片段1的构造函数中optionalValue后面是问号( ? )。这里的感叹号( ! )是指强解析,你也可以理解为强制取值,但是optionalValue至定义后从未赋值过,也就是没有值(特别注意:可选值不是值),自然也就和代码片段1报一样的错

方法参数

class MyClass {
    
    var value: String!
    var optionalValue: String?// defaulit is nil
    
    func hello(_ say: String, to: String?) {
        
    }
}
到这里相信大家对叹号( ! )与问号( ? )有一定的了解,这里就简单说一下:hello方法中say参数是非可选类型,to是可选类型,方法中的非可选类型并不需要显示定义,也就是叹号( ! )可以省略。

总结

  • 叹号( ! )根据不同场景有2层意思:非选类型和强解析
  • 问号( ? )根据不同场景有2层意思:可选类型和弱解析
  • 叹号( ! )使用时如果没有值会导致崩溃,问号( ? )进行强解析时如果没有值会导致崩溃
  • 一般来说能否确定有值是定义可选类型还是非可选类型的一项标准
  • 可选值不是值

如何正确解析可选类型

  • 方法1
guard let realValue = optionalValue else {
            
   return
}

// do something
如果optionalValue有值就赋值给realValue,然后继续执行后面的代码,否则直接返回
  • 方法2
 if let realValue = optionalValue {

    // do something
  }
如果optionalValue有值就赋值给realValue,然后执行代码{}中的代码,否则继续执行后面的代码

本文由 Harvey 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

2 条评论

  1. 时默
    时默

    虽然看不懂,但还是大佬牛逼

  2. Peter
    Peter

    var value: String!
    这个value,不能说必须要有值,它的意思是使用的时候会强制拆包,nil的时候强制拆包会异常,只要没有使用,一直是nil都没有关系

添加新评论