认识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() 
上一篇下一篇

猜你喜欢

热点阅读