Swift-OtherSynatax-Optional和类型转换
2020-11-26 本文已影响0人
守护地中海的花
可选项 ?
- 可选项,一般也叫可选类型,它允许将值设置为nil
- 在类型名称后面加个问号
?
来定义一个可选项
类比盒子
- 可选项是对其他类型的一层包装,可以将它理解为一个盒子
- 如果为nil,那么它是个空盒子
- 如果不为nil,那么盒子里装的是:被包装类型的数据
var age: Int? //默认就是nil
print(age)//nil
age = 10
print(age)//Optional(10)
控制台打印:
nil
Optional(10)
数组案例
var array = [1,15,40,29]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
print(get(1))//Optional(15)
print(get(-1))
print(get(4))
强制解包(Forced Unwrapping)
//正确的解包
let forcedAge:Int = age!
print(forcedAge)
//下面运行会报错
var ageNil: Int?
//print(ageNil!)
//Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
- 如果要从可选项中取出被包装的数据(将盒子里面的东西取出来),需要使用感叹号!进行强制解包
-
如果对值为nil的可选项(空盒子)进行强制解包,将会产生运行时错误
image.png
判断可选项是否包含值---> 可选项绑定(Optional Binding)
let numer = Int("123")
if numer != nil {
print("字符串转换整数成功:\(numer!)")
} else {
print("字符串转换整数失败")
}
上面判断很麻烦下面就是语法的缩写
image.png
if let numer1 = Int("123") {
print("可选项绑定 if let 字符串转换成功",numer1)
} else {
print("字符串转换失败")
}
enum Season : Int {
case spring = 1,summer,autumn,winter
}
if let season = Season(rawValue: 6) {
print(season)
} else {
print("没有这个Season")
}
- 可以使用 可选项绑定 来判断可选项是否包含值
- 如果包含就自动解包,把值赋给一个临时的变量或常量 并返回true 否则返回false (这个值是临时的 只能在{}里面使用或者该声明后面如等价写法和while的例子)
等价写法
if let first = Int("4") {
if let second = Int("42") {
if first < second && second < 100 {
print("\(first)<\(second)<\(100)")
}
}
}
if let first = Int("4"),let second = Int("42") ,first < second && second < 100 {
print("\(first)<\(second)<\(100)")
}
while循环中使用可选项绑定
var strs = ["10","20","abc","-20"]
var index = 0
var sum = 0
while let num = Int(strs[index]),num > 0 {
sum = sum + num
index += 1
print("index = \(index)")
}
print(sum)
空合并运算符??(Nil-Coalescing Operator)
var a: Int? = 10
var b: Int = 10
print(a ?? b)
控制台
10
- a 是可选项
- b 可以不是可选项
- b跟a的存储类型必须相同
- 如果a 不为nil ,就返回a
- 如果a 为nil 就返回b
- 如果b不是可选项,返回a时会自动解包
let e: Int? = nil
let f: Int? = 2
if let g = e ?? f {
print("if let ?? \(g)")
}
控制器:
if let ?? 2
案例 if let -> guard
func login(_ info:[String: String]) -> Bool {
var userName: String,password: String
if let tmp = info["username"] {
userName = tmp
} else {
print("请输入用户名")
return false
}
if let tmp = info["password"] {
password = tmp
} else {
print("请输入用户密码")
return false
}
print(userName,password)
return false
}
login(["username": "jack"])
login(["password":"123456"])
login(["username": "jack","password":"123456"])
image.png
func login1(_ info:[String: String]) {
guard let username = info["username"] else {
print("请输入用户名")
return
}
guard let password = info["password"] else {
print("请输入密码")
return
}
var age: Int?
guard let tmpAge = age else {
print("真的进来了!")
return
}
print(username,password)
login1(["username": "jack"])
login1(["password":"123456"])
login1(["username": "jack","password":"123456"])
}
控制台打印:
请输入密码
请输入用户名
真的进来了!
隐式解包(Implicitly Unrwapped Optional)
- 在某些情况下,可选项一旦被设定值之后,就会一直拥有值
- 在这种情况下,可以去掉检查,也不必每次访问的时候都进行解包,因为它能确定每次访问的时候都有值
- 可以在类型后面加个感叹号!定义一个隐式解包的可选项
let num1: Int! = 10
let num2: Int = num1
if num1 != nil {
print(num1 + 6)
}
let num3: Int! = nil
//Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
//let num4: Int = num3
字符串插值
/**
* 这些都交给编译器 会自己修复
*/
var agea: Int? = 10
print(agea)
/**
* Expression implicitly coerced from 'Int?' to 'Any'
* Provide a default value to avoid this warning 【Fix】---> agea ?? <#default value#>
* Force-unwrap the value to avoid this warning [Fix] ---> agea!
* Explicitly cast to 'Any' with 'as Any' to silence this warning agea as Any
*/
print("\(agea)")
/**
* String interpolation produces a debug description for an optional value; did you mean to make this explicit?
* Use 'String(describing:)' to silence this warning [Fix] -->\(String(describing: agea))
* Provide a default value to avoid this warning [Fix] --> agea ?? 0
*/
多重可选项
func more () {
var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
print(num2 == num3)
print("num2=\(num2)","num2!=\(num2!)","num2!!=\(num2!!)")
}
func more2() {
var num1: Int? = nil
var num2: Int?? = num1
var num3: Int?? = nil
print(num2 == num3)
}
more()
more2()
控制台:
true
num2=Optional(Optional(10)) num2!=Optional(10) num2!!=10
false
image.png
image.png
可选链概念
- 如果可选项为nil,调用方法、下标、属性失败,结果为nil
- 如果可选项不为nil,调用方法、下标、属性成功,结果会被包装可选项
- 如果结果本来就是可选项,不会进行再次包装
- 多个?可以连接在一起
- 如果链中任何一个节点是nil,那么整个链就会调用失败
class Car {
var price = 0
}
class Dog {
var weight = 0
}
class Person {
var name: String = ""
var dog: Dog = Dog()
var car:Car? = Car()
func age() -> Int {
18
}
func eat() {
print("Person eat")
}
subscript(index: Int) -> Int {
index
}
}
var person:Person? = Person()
print(person is Person)// true
print(person?.age())// Optional(18)
print(person!.age())// 18
print(person?[6])// Optional(6)
Any,AnyObject
var stu: Any = 10
stu = "jack"
print(stu)
stu = Person()
print(stu)
var data = [Any]()
data.append(1)
data.append("222")
data.append({10})
- Swift提供了2种特殊的类型:Any、AnyObject
- Any:可以代表任意类型(枚举、结构体、类,也包括函数类型)
- AnyObject:可以代表任意类类型(在协议后面写上:AnyObject代表只有类能遵守这个协议)在协议后面加上class 也是代表只有类能遵守这个协议
is、as?、as!、as
print(stu is String)
print(stu is Person)
stu = "wpp"
(stu as? Person)?.eat()
stu = Person()
(stu as? Person)?.eat()
(stu as! Person).eat()
- is用来判断是否为某种类型,as 用来做强制类型转换
- !强制解包
- ?可选