Swift 可选类型

Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。
Swfit语言定义后缀?作为命名类型Optional的简写,换句话说,以下两种声明是相等的:

var optionalInteger: Int?
var optionalInteger: Optional

注意:在类型和 ?之间没有空格。

在这两种情况下,变量 optionalInteger 都是可选整数类型。
Optional 是一个含有两种情况的枚举,NoneSome(T),用来表示可能有或可能没有值。任何类型都可以明确声明为(或者隐式转换)可选类型。当声明一个可选类型的时候,要确保用()? 操作符一个合适的范围。例如,声明可选整数数组,应该写成 (Int[])? ,写成 Int[]? 会报错。当你声明一个可选变量或者可选属性的时候没有提供初始值,它的值会默认为 nil。可选项遵照 LogicValue 协议,因此可以出现在布尔环境中。在这种情况下,如果可选类型T?包含类型为T的任何值(也就是说它的值是 Optional.Some(T) ),这个可选类型等于 true,反之为 false
如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值,如下所示:

optionalInteger = 42
optionalInteger! // 42

注意:使用操作符!去获取值为nil的可选变量会有运行时错误。

你可以用可选链接和可选绑定选择性执行可选表达式上的操作。如果值为nil,任何操作都不会执行,也不会有运行报错。
让我们来详细看下以下实例来了解 Swift 中可选类型的应用:

import Cocoa

var myString:String? = nil

if myString != nil {
    print(myString)
}else{
    print("字符串为 nil")
}

以上程序执行结果为:

字符串为 nil

可选类型类似于Objective-C中指针的nil值,但是nil只对类(class)有用,而可选类型对所有的类型都可用,并且更安全。

强制解析

当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号!来获取值。这个感叹号表示"我知道这个可选有值,请使用它。"这被称为可选值的强制解析(forced unwrapping)。
实例如下:

import Cocoa

var myString:String?

myString = "Hello, Swift!"

if myString != nil {
   print(myString)
}else{
   print("myString 值为 nil")
}

以上程序执行结果为:

Optional("Hello, Swift!")

强制解析可选值,使用感叹号!

import Cocoa

var myString:String?

myString = "Hello, Swift!"

if myString != nil {
   // 强制解析
   print( myString! )
}else{
   print("myString 值为 nil")
}

以上程序执行结果为:

Hello, Swift!

注意:使用!来获取一个不存在的可选值会导致运行时错误。使用!来强制解析值之前,一定要确定可选包含一个非nil的值。

自动解析

你可以在声明可选变量时使用感叹号!替换问号?。这样可选变量在使用时就不需要再加一个感叹号!来获取值,它会自动解析。实例如下:

import Cocoa

var myString:String!
myString = "Hello, Swift!"

if myString != nil {
   print(myString)
}else{
   print("myString 值为 nil")
}

以上程序执行结果为:

Hello, Swift!

使用可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在ifwhile语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。
像下面这样在if语句中写一个可选绑定:

if let constantName = someOptional {
    statements
}

让我们来看下一个简单的可选绑定实例:

import Cocoa

var myString:String?

myString = "Hello, Swift!"

if let yourString = myString {
   print("你的字符串值为 - \(yourString)")
}else{
   print("你的字符串没有值")
}

以上程序执行结果为:

你的字符串值为 - Hello, Swift!

as, as!as? 的使用

  • as
    keyword:Guaranteed conversion、 Upcasting
    理解:字面理解就是有保证的转换,从派生类转换为基类的向上转型
    实例:
// 将1转成float 
let num = 1 as CGFloat 
// dog转换到父类animal 
class Animal {} 
class Dog: Animal {} 
let d = Dog() 
d as Animal
  • as!
    keyword:Forced conversion、 Downcasting
    理解:字面理解就是有强项转换,即向下转型,子类(派生类)向父类转换,官方解释说这是一个不被保证的转换,可能会因为强转的失败而会导致崩溃。同时!是一个陷阱的标志,就像⚠️一样,用起来存在一定危险性。
class Animal {}
class Cat: Animal {}
let animal :Animal  = Cat()
let cat = animal as! Cat
  • as?
    keyword:Optional、 Nil
    理解:Swfit代码写一段时间后会发现到处都是 ? ,这预示着如果转换不成功的时候便会返回一个 nil 对象。成功的话返回可选类型值(optional),需要我们拆包使用。由于 as? 在转换失败的时候也不会出现错误,所以对于如果能确保100%会成功的转换则可使用 as!,否则使用 as?
// Dog、Cat和Animal的转换关系 
class Animal {} 
class Cat: Animal {} 
class Dog: Animal 
{ 
    var name = "Spot" 
} 

let dog: Dog? = nil 
dog?.name // 选择调用,返回空值nil 
dog!.name // 强行调用,报错 

let animal: Animal = Cat() 
animal as? Dog // 猫转狗失败,返回nil 
animal as! Dog // 猫强行转狗,失败报错

可选类型在错误处理中使用(try!try?

  • try?
    try?会将错误转换为可选值,当调用try?+函数或方法语句时候,如果函数或方法抛出错误,程序不会发崩溃,而返回一个nil,如果没有抛出错误则返回可选值。
func someThrowingFunction() throws -> Int {
    // ...
}

let x = try? someThrowingFunction()

x可能正常返回一个Int类型的值也有可能抛出一个错误异常,使用时对x用if let可选绑定判断

  • try!
    使用try!可以打破错误传播链条。错误抛出后传播给它的调用者,这样就形成了一个传播链条,但有的时候确实不想让错误传播下去,可以使用try!语句
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

上述语句中在执行loadImage方法时如果执行失败,使用try!来禁用错误传递,会有运行错误导致App崩溃

你可能感兴趣的:(Swift 可选类型)