美文网首页
认识Swift系列5之可选项

认识Swift系列5之可选项

作者: Niuszeng | 来源:发表于2019-07-11 19:06 被阅读0次
        // 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() 
    

    相关文章

      网友评论

          本文标题:认识Swift系列5之可选项

          本文链接:https://www.haomeiwen.com/subject/rfhjkctx.html