一、
Optional其实是个enum,里面有None和Some两种类型。其实所谓的nil就是Optional.None , 非nil就是Optional.Some, 然后会通过Some(T)包装(wrap)原始值,这也是为什么在使用Optional的时候要拆包(从enum里取出来原始值)的原因。

 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
}
例如:
class ViewController: UIViewController {
    var textLabel: UILabel?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
    }
}

定义textLabel为一个可选类型,是可能存在nil的情况;
那么使用的时候,必须进场解包;
textLabel?.tag = 100
如果没有进行初始化,那么?解出来的是nil ,运行正常;
textLabel!.tag = 100,则直接崩溃;
因为:如果是nil值,也就是Optional.None,会跳过后面的操作不执行,如果有值,就是Optional.Some,可能就会拆包(unwrap),然后对拆包后的值执行后面的操作,来保证执行这个操作的安全性。

解包的方式:
1:可选拆包:一种更简单更推荐的方法来解包一个可选类型。 使用可选绑定来检查可选类型的变量有值还是没值。如果有值, 解包它并且将值传递给一个常量或者变量。

// 例子最为简单明了
var str: String? = "Hello"
let greeting = "World!"
if let name = str {
  let message = greeting + name
  print(message)
}
func getHeight(_ height: Float?) -> Float? {
    guard let unwrapedHeight = height else {
         return nil
     }
     return unwrapedHeight / 100
}
/**
自然语言解释意思:就是如果str有值,解包它,并且将它的值赋值给name, 然后执行下面的条件语句; 如果str为空, 直接跳过条件语句块。
*/

2:硬解包:即直接在可选类型后面加一个感叹号(!)来表示它肯定有值。

var str1: String? = "Hello"
let greeting = "World!"
if (str1 != nil) {
  let message = greeting + str1!
  print(message)
}
/**
上面例子,我们只是自己知道str1肯定有值, 所以才直接硬解包了str1变量。 但是万一有时候我们的感觉是错的, 那程序在运行时可能会出现严重的错误. 所以Swift中是推荐先检查可选类型是否有值, 然后再进行解包的!
*/

3:隐式拆包:

var textLabel: UILabel!

最后,有解包,就有封包,什么是封包呢?
简单来就是将一种确定的数据类型转换为可选类型(Optional)的过程,我们称之为封包。例如:将String类型转换为Optional String类型的过程,其实就是一种封包过程。
// 显示封包
let nameStr: String? = "test Name"
// 隐式封包
let nameStr: String! = "my Name"

二、as as! as? 的用法
as: 有保证的转换,从派生类转换为基类的向上转型(upcasts)

class Animal {}
class Cat: Animal {}
let cat = Cat()
let animal = cat as Animal

as!: 向下转型(Downcasting)时使用,子类(派生类)向父类转换,如果转换失败会报 runtime 运行错误。
官方解释说这是一个不被保证的转换,可能会因为强转的失败而会导致崩溃。同时!是一个陷阱的标志,就像⚠️一样,用起来存在一定危险性。*

class Animal {}
class Cat: Animal {}
let animal :Animal  = Cat()
let cat = animal as! Cat

as?: [as?] 和 [as!] 操作符的转换规则完全一样。但 [as?] 如果转换不成功的时候便会返回一个 nil 对象