认识Swift系列5之可选项
2019-07-11 本文已影响0人
Niuszeng
// 1.声明
func test_declaration() {
// 可选项,一半也叫可选类型,允许将值设置为nil
// 在类型后边加一个?来定义一个可选项,通常使用var定义
var name: String? = "Rose" // 声明时可以给初始值
name = nil // 过后也可以将该值设置为nil
var age: Int? // 声明时不给初始值,默认为nil
age = 10 ; age = nil // 后边可以赋值也可以清空
// 应用,函数返回值可能为空
var array = [1, 2, 3, 4]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index];
}
}
test_declaration()
// 2.强制解包
func test_forced_unwrapping() {
// 可以将可选类型理解为一个盒子
// 如果值为nil,那么是个空盒子
// 如果值不为nil,那么盒子中装有被包装的数据类型
var age: Int? // 步骤1,声明
age = 10 // 步骤二,赋值
age = nil // 步骤三,清空
/**
步骤1,声明了一个空盒子
┏━━━━━━━━━━━━━━━━┓
┃ age: Int? ┃
┃ ┃
┃ ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━┛
步骤2赋值,向盒子中装入要包装的数据
┏━━━━━━━━━━━━━━━━┓
┃ age: Int? ┃
┃ ┏━━━━━━━━━━━━┓ ┃
┃ ┃ Int ┃ ┃
┃ ┃ 10 ┃ ┃
┃ ┗━━━━━━━━━━━━┛ ┃
┗━━━━━━━━━━━━━━━━┛
步骤3清空,清空盒子
┏━━━━━━━━━━━━━━━━┓
┃ age: Int? ┃
┃ ┃
┃ ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━┛
*/
// 解包,可以理解为将盒子中的数据取出来
// 使用感叹号进行强制解包,但是如果盒子是空的,可能会造成crash
// ! 表示表示危险操作,警告危险⚠️标识
let number1: Int? = 10
let tempNumber1 = number1!
print("tempNumber1 is \(tempNumber1)")
// 如下代码报错
// Fatal error: Unexpectedly found nil while unwrapping an Optional value
// var number2: Int?
// let tempNumber2 = number2!
// print("tempNumber2 is \(tempNumber2)")
// 应用,字符串转整数字
// 该过程不知道是否会转换成功,比如字符串如果是“abc”,因此返回可选类型
let number3 = Int("123")
if number3 != nil { // 使用之前先判断
// 这里能确定有值,可使用强制解包
print("number3 is \(number3!)")
} else {
print("number3 is nil")
}
}
test_forced_unwrapping()
// 3.可选值绑定
func test_optional_binding() {
// 该方法是使用条件语句来判断是否包含值
// 如果包含值会自动解包给var或let,并返回true,否则返回false
// 普通绑定解包
if let number = Int("aa123") {
// 这个if语句做了两件事
// 1.判断 Int("123") 是否包含值(盒子中是否有东西)
// 2.有东西,将值取出给到number(解包),让该表达式返回true,进入if语句块
// 无东西,让该表达式返回false,进入else语句块
print("number binding is \(number)")
} else {
print("number binding is none")
}
// 枚举绑定解包
enum Enum: Int {case a = 1, b, c, d}
if let e = Enum(rawValue: 3) {
print("e is \(e)")
} else {
print("no such e")
}
// 多个值依赖解包等价写法
if let first = Int("1") {
if let second = Int("2") {
if first < second && second < 10 {
print("\(first) < \(second) < 100")
}
}
}
// 等价于
if let first = Int("1"), let second = Int("2"), first < second && second < 10 {
// 绑定和判断值之间可以逗号分开放在一起,但是注意,存储在依赖的判断要放在解包之后
print("\(first) < \(second) < 100")
}
// while循环可选项绑定
var arr = ["10", "20", "abc", "-20", "30"];
var index = 0
var sum = 0
while let num = Int(arr[index]), num > 0 {
sum += num
index += 1
}
print("arr sum binding is \(sum)")
}
test_optional_binding()
// 4.空合并运算符"??"
func test_nil_coalescing_operator() {
/** a ?? b
a 和 b类型必须相同(广义相同): a必须是可选类型,b是不是可选都行
如果a为不为nil,返回a,否则返回b(若b是非可选类型,返回a时会自动解包)
即:返回值类型以b为准(b是什么类型,这个表达式就返回什么类型)
*/
let a1: Int? = 1
let b1: Int? = 2
let c1 = a1 ?? b1
print("??1 \(String(describing: c1))")
let a2: Int? = 1
let b2: Int = 2
let c2 = a2 ?? b2
print("??2 \(String(describing: c2))")
let a3: Int? = nil
let b3: Int? = 2
let c3 = a3 ?? b3
print("??3 \(String(describing: c3))")
let a4: Int? = nil
let b4: Int = 2
let c4 = a4 ?? b4
print("??4 \(String(describing: c4))")
// 多个 ?? 一起使用时,可从左向右分析
let aa1: Int? = 1
let bb1: Int? = 2
let cc1 = aa1 ?? bb1 ?? 3 // optional(1)->1
print("??5 cc1 is \(cc1)")
let aa2: Int? = nil
let bb2: Int? = 2
let cc2 = aa2 ?? bb2 ?? 3 // optional(2)->2
print("??6 cc2 is \(cc2)")
let aa3: Int? = nil
let bb3: Int? = nil
let cc3 = aa3 ?? bb3 ?? 3 // nil->3
print("??7 cc3 is \(cc3)")
// ?? 配合 if let绑定
if let tm1 = a1 ?? b1 {
// 该是式子只有a1和b1有一个存在就会自动解包给tm1,并返回true
// 类似:if a != nil || b != nil
print("tm1 is \(tm1)")
}
if let tm1 = a1 , let tm2 = b1 {
// 必须两个都返回true,即两个都解包成功
// 类似:if a != nil && b != nil
print("tm1 is \(tm1) and tm2 is \(tm2)")
}
}
test_nil_coalescing_operator()
// 5.guard语句
func test_guard() {
/**
guard 条件 else {
// your code...
// 退出当前作用域
return、break、continue、throw error
}
当条件为false的时候,会进入大括号
当条件为true的时候,会跳过大括号
guard 时候用来做提前退出
注意:guard 条件绑定的 let或var能够在外层作用域使用
*/
print("guard is start!")
let test: Int? = 10
guard let tmp = test, tmp == 11 else {
print("guard is ...")
return
}
print("guard is end! \(tmp)")
}
test_guard()
// 6.隐式解包
func test_implicitly_unwrapped_optional() {
// 在某些情况下,确定某个可选类型有值得时候可以使用隐式可选类型,使用时会自动解包
let number: Int! = Int("1243");
// 1.直接致命number2的接收类型,会自动隐式解包
let number2: Int = number
print("implicitly_unwrapped number2 is \(String(describing: number2))")
// 2.使用if可选绑定
if let number3 = number {
print("implicitly_unwrapped number3 is \(String(describing: number3))")
}
}
test_implicitly_unwrapped_optional()
// 7.多重可选项
func test_mutipule_optional() {
let num1: Int? = 10
let num2: Int?? = num1
let num3: Int?? = 10
print("mutipule_optional num3 == num2 is \(num3 == num2)")
/**
num1
┏━━━━━━━━━━━━━━━━┓
┃ age: Int? ┃
┃ ┏━━━━━━━━━━━━┓ ┃
┃ ┃ Int ┃ ┃
┃ ┃ 10 ┃ ┃
┃ ┗━━━━━━━━━━━━┛ ┃
┗━━━━━━━━━━━━━━━━┛
num2
┏━━━━━━━━━━━━━━━━┓
┃ age: Int?? ┃
┃ ┏━━━━━━━━━━━━┓ ┃
┃ ┃ Int? ┃ ┃
┃ ┃ ┏━━━━━━┓ ┃ ┃
┃ ┃ ┃ Int ┃ ┃ ┃
┃ ┃ ┃ 10 ┃ ┃ ┃
┃ ┃ ┗━━━━━━┛ ┃ ┃
┃ ┗━━━━━━━━━━━━┛ ┃
┗━━━━━━━━━━━━━━━━┛
num3
┏━━━━━━━━━━━━━━━━┓
┃ age: Int?? ┃
┃ ┏━━━━━━━━━━━━┓ ┃
┃ ┃ Int? ┃ ┃
┃ ┃ ┏━━━━━━┓ ┃ ┃
┃ ┃ ┃ Int ┃ ┃ ┃
┃ ┃ ┃ 10 ┃ ┃ ┃
┃ ┃ ┗━━━━━━┛ ┃ ┃
┃ ┗━━━━━━━━━━━━┛ ┃
┗━━━━━━━━━━━━━━━━┛
*/
let num11: Int? = nil
let num22: Int?? = num11
let num33: Int?? = nil
print("mutipule_optional num33 == num22 is \(num33 == num22)")
/**
num1
┏━━━━━━━━━━━━━━━━┓
┃ age: Int? ┃
┃ ┃
┃ ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━┛
num2
┏━━━━━━━━━━━━━━━━┓
┃ age: Int?? ┃
┃ ┏━━━━━━━━━━━━┓ ┃
┃ ┃ Int? ┃ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┃ ┗━━━━━━━━━━━━┛ ┃
┗━━━━━━━━━━━━━━━━┛
num3
┏━━━━━━━━━━━━━━━━┓
┃ age: Int?? ┃
┃ ┃
┃ ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━┛
*/
}
test_mutipule_optional()