Swift3-06 可选型 Optionals

画重点! Optionals 是 swift 新加入的类型,所以之前的 Objective-C 中是没有这个概念的。可选型 简单一些理解就是:有值的时候就有值,无值的时候 是 nil. 但是 swift 的 nil 和其他语言中的 nil 不一样,nil 本身也是一中类型,nil就是没有,不是任何一个值,是和其他类型严格区分开的。

可选型不是表示 可以表示任意类型,而是可以表示一个指定数据类型 和 nil类型,

错误代码示范

var name: String = "loveway"
name = nil //报错 error: Nil cannot be assigned to type 'String'

Optionals的声明 var optionalInteger: Int? , var optionalInteger: Optional<Int>

var name: String? = "loveway"
print(name!)
name = nil
print(name as Any)

可选型的解包

var name: Optional<String> = "lazy"
print(name!)
name = nil
print(name as Any )
name = "sam"
//var string = "my name is " + name  //error 因为 ```name```是一个未解包的数据,不能直接使用。
var string = "my name is " + name!  //强制解包

后面加一个 叹号 ! 可以强制解包 但是 name 有可能出现为 nil 的情况,这是有风险的。可能 会造成 app 崩溃。所以在使用之前需要对 name 进行判空

var name: Optional<String> = "lazy"
var age : Optional<Int> = 24

if name != nil {
    var string = "my name is " + name!
}else{
     "name is nil"
}

//或者
if let unwrapName = name{ //自动解包 name 数据到 unwrapName
    var string = "my name is " + unwrapName
}else{
          "name is nil"
}

两个数据都解包成功之后才会进入判断方法中。

if let unwrapName = name,let unwrapAge = age{
    var string = "my name is " + unwrapName + "age is \(unwrapAge)"
}

添加限制条件

if let unwrapName = name,let unwrapAge = age , unwrapAge > 20{
    var string = "my name is " + unwrapName + "age is \(unwrapAge)"
}

if let name = name,let age = age , age > 20{
    var string = "my name is " + name + "age is \(age)"
}

Optional Chaining

var errorMsg:String? = nil
print(errorMsg as Any)
errorMsg = "404"
//重点 尝试解包 ```?```
errorMsg?.uppercased() //尝试解包,如果成功就调用方法,如果失败,就停止 

//如果确认 ```errorMsg```有值,可以使用,否则很容易出错。 
errorMsg!.uppercased() //强制解包,如果 ```errorMsg``` 是 nil 则会报错,这样写会不安全。

var temp = errorMsg?.uppercased() //temp 依然是一个可选型

var msg = errorMsg == nil ? "No error" : errorMsg!

Optional在元组中的使用

var error :(errorCode: Int , errorMsg:String?) = (404, "Not found")
error.errorMsg = nil

var error1 :(errorCode: Int , errorMsg:String)? = nil
error1 = nil

var error2 :(errorCode: Int , errorMsg:String?)? = nil
error2?.errorMsg = nil
error2 = nil

Optional 的应用

var ageInput:String = "ads"
var age = Int(ageInput) //返回的 age 类型是可选型。
if let age = Int(ageInput), age > 18{ //这里的 age 的类似又是什么呢? 
    print("成年了")
}


var str = "hello world"
var range =  str.range(of: "ll")
range?.lowerBound
range?.upperBound

隐式可选型 隐式可选型在使用的时候可以不进行解包直接使用。

var errorMsg:String! = nil
errorMsg = "Not found"
"messge " + errorMsg  //使用的时候必须保证 errorMsg 不为空,要不然程序会报错。




class Student{
    let name:String
    var age:Int
    var stdId:Int
    unowned var aClass:Class //避免循环引用
    init(name:String,age:Int,stdId:Int,aClass:Class){
        self.name = name
        self.age = age
        self.stdId = stdId
        self.aClass = aClass
    }
}

class Class{
    var className:String = ""
    var classNum:Int = 0
    var monitor:Student! //若不设置成可选型,则在下面初始化的时候回造成死循环

    init(className:String, classNum:Int, monitorName:String) {
        self.className = className;
        self.classNum = classNum;
        self.monitor = Student(name: monitorName, age: 18, stdId: 20, aClass: self)
    }
    func showInfo(){
        print("this is \(classNum)")
        print("monitor is \(monitor.name)")
    }
}

let class001 = Class(className: "0101", classNum: 1001, monitorName: "jack")
class001.monitor
class001.showInfo()