Swift5.0 - day2-流程控制黎休、函數(shù)、枚舉

一玉凯、流程控制

  • 1.1势腮、if 語(yǔ)句

    let age = 5
    if age > 10  {
        print("\(age) 大于 10 ")
    } else if  age > 3 {
        print("\(age) 大于 3 ")
    } else {
        print("\(age) 小于 3 ")
    }
    

    提示:

    • if 后面的條件可以省略小括號(hào),而條件后面的花括號(hào)不可以省略
    • if 后面的類型只能是 bool 類型


      if 后面的類型只能是 bool 類型
  • 1.2漫仆、while 語(yǔ)句(先判斷后執(zhí)行)

    var num = 5
    while num > 0 {
         num -= 1
         print("num=\(num)")
    }
    

    打印結(jié)果:num=4捎拯、num=3、num=2盲厌、num=1署照、num=0

  • 1.3、repeat while 語(yǔ)句(先執(zhí)行后判斷)

    var num = -1
    repeat{
        print("num=\(num)")
    }while num > 0
    

    打印結(jié)果:num=-1吗浩,

    提示:repeat-while 相當(dāng)于 OC 里面的 do-while

  • 1.4建芙、for 語(yǔ)句

    • 閉區(qū)間運(yùn)算符:a...ba<= 取值 <=b

      let names = ["小1","小2","小3","小4"]
      for i in 0...3 {
           print("name=\(names[i])")
      }
      

      提示:上面的 0...3 可以替換為 let range = 0...3

      let a =  0
      var b = 3
      
      let names = ["小1","小2","小3","小4"]
      for i in a...b {
          print("name=\(names[i])")
      }
      

      提示:區(qū)間可以用常量或者變量來表示的

      for _ in 0...3 {
          print("??")
      }
      

      打印了 四次 ??

    • for 循環(huán)里面的 i 默認(rèn)是 let拓萌,有需要的時(shí)候我們可以聲明為 var,如下

      for var i in 1...3 {
          i += 2
          print("i=\(i)")
      }
      

      打印結(jié)果:3岁钓、4、5

    • 半開區(qū)間運(yùn)算符:a..<b微王;a <= 取值 < b

      for i in 1..<3 {
      
         print("i=\(i)")
      }
      

      打印結(jié)果:1屡限、2

  • 1.5、for - 區(qū)間運(yùn)算符用在數(shù)組上

    • 例一

      let names = ["小1","小2","小3","小4"]
      for name in names[0...3] {
           print("name=\(name)")
      }
      

      打印結(jié)果:小1炕倘、小2钧大、小3、小4

    • 例二:?jiǎn)蝹?cè)區(qū)間:讓區(qū)間朝一個(gè)方向盡可能的遠(yuǎn)

      let names = ["小1","小2","小3","小4"]
      for name in names[1...] {
          print("name=\(name)")
      }
      

      打印結(jié)果:小2罩旋、小3啊央、小4

      let names = ["小1","小2","小3","小4"]
      for name in names[...2] {
          print("name=\(name)")
      }
      

      打印結(jié)果:小1、小2涨醋、小3

      let names = ["小1","小2","小3","小4"]
      for name in names[..<2] {
          print("name=\(name)")
      }
      

      打印結(jié)果:小1瓜饥、小2

      let range = ...5
      print(range.contains(8))
      print(range.contains(3))
      print(range.contains(-1))
      

      打印結(jié)果:false、true浴骂、true

      提示: let range = ...5 代表 range的范圍從無窮小到 5乓土,包含5

  • 1.6、區(qū)間類型(重點(diǎn))

    let range1:ClosedRange<Int> = 1...3
    let range2:Range<Int> = 1..<3
    let range3:PartialRangeThrough<Int> = ...5
    
    • 字符溯警、字符串也能進(jìn)行區(qū)間運(yùn)算趣苏,但默認(rèn)不能在 for-in 中,因?yàn)?ClosedRange:不可數(shù)的閉區(qū)間

      let stringRange1 = "cc"..."ff" // ClosedRange<String>
      stringRange1.contains("cb")   // false
      stringRange1.contains("dz")   // true 
      stringRange1.contains("fg")   // false
      
      let stringRange2 = "a"..."f"  // ClosedRange<String>
      stringRange2.contains("d")    // true
      stringRange2.contains("n")    // false
      

      提示:比較的是ascii梯轻,第1位比較第1位食磕,第2位比較第2位,如果第1位大于第1位就沒必要比較第二位了喳挑,依次類推


      Ascii字符表
    • 0到~包含了所有可能要用到的 ASCII 字符

      let characterRange:ClosedRange<Character> = "\0"..."~"
      characterRange.contains("b")   // true
      
  • 1.8彬伦、帶間隔的區(qū)間值

    let hours = 12
    let hourInterval = 2
    // 從tickMark 的取值:從 4 開始,累加2伊诵,不超過 12
    for tickMark in stride(from: 4, to: hours, by: hourInterval) {
        print("tickMark=\(tickMark)")
    }
    

    打印結(jié)果:4媚朦、6、8日戈、10

  • 1.9询张、switch 語(yǔ)句

    • 案例一:switch的基本使用

      var num = 10
      switch num {
      case 1:
           print("值是1")
           break
      case 2:
           print("值是2")
           break
      case 3:
           print("值是3")
           break
      default:
           print("沒有匹配")
           break
      }
      

      提示:case 和 default 后面不能寫大括號(hào) {},默認(rèn)可以不寫 break浙炼,并不會(huì)貫穿到后面的條件

    • 案例二:使用 fallthrough 可以實(shí)現(xiàn)貫穿效果

      var num = 1
      switch num {
      case 1:
         print("num 值是 1")
         fallthrough
      case 2:
         print("num 值是 2")
      case 3:
         print("num 值是 3")
      default:
         print("沒有匹配")
      }
      

      打印結(jié)果:num 值是 1份氧、num 值是 2

    • switch使用注意點(diǎn):

      • <1>、switch 必須能保證處理所有的情況


        switch 必須能保證處理所有的情況
      • <2>弯屈、case 或者 default 后面至少有一條語(yǔ)句蜗帜,如果不想有語(yǔ)句可以寫 break

        var num = 1
        switch num {
        case 1:
            print("num 值是 1")
        case 2:
            break
        default:
            print("沒有匹配")
        }
        
      • <3>、如果能保證處理所有的情況资厉,也可以不必使用 default,如下

        enum Answer {case right,wrong}
        let answer = Answer.right
        switch answer {
        case Answer.right:
            print("right")
        case Answer.wrong:
            print("wrong")
        }
        

        提示:上面已經(jīng)確定 answer 是 Answer 類型厅缺,因此可以省略 Answer

        enum Answer {case right,wrong}
        let answer = Answer.right
        switch answer {
        case .right:
             print("right")
        case .wrong:
             print("wrong")
        }
        
    • 復(fù)合條件:switch也支持Character、String 類型,如下例子

      • 例一:String 類型

        let name = "marry"
        switch name {
        case "Jack":
            print("Jack")
        case "marry":
            print("marry")
        default:
            print("找不到某人")
        }
        
      • 例二:String 類型

        let name = "marry"
        switch name {
        case "Jack","marry":
            print("Jack and marry")
        default:
            print("找不到某人")
        }
        
      • 例三:Character 類型

        let character = "A"
        switch character {
        case "a","A":
            print("字母 a或者A")
        default:
            print("找不到字母")
        }
        
    • 匹配區(qū)間和元組匹配

      • 匹配區(qū)間

        let count = 20
        switch count {
        case 0:
           print("none")
        case 1..<5:
           print("a few")
        case 5..<100:
           print("several")
        case 100..<1000:
           print("hundreds of")
        default:
           print("many")
        }
        
      • 元組匹配

        let point = (1,1)
        switch point {
        case (0,0):
           print("the origin")
        case (_,0):
           print("on the x-axis")
        case (0,_):
           print("on the y-axis")
        case (-2...2,-2...2):
           print("inside the box")
        default:
           print("many")
        }
        

        提示:可以使用 _ 忽略某個(gè)值

    • 值綁定:必要時(shí)湘捎,let 可以改為 var

      let point = (2,0)
      switch point {
      case (let x,0):
         print("on the x-axis with an x value of \(x)")
      case (0,let y):
         print("on the y-axis with an y value of \(y)")
      case let (x,y):
         print("somehere else at (\(x),\(y))")
      }
      
  • 1.10诀豁、where語(yǔ)句

    let point = (2,-2)
    switch point {
    case let (x,y) where x == y:
        print("on the line x == y")
    case let (x,y) where x == -y:
        print("on the line x == -y")
    case let (x,y):
        print("(\(x),\(y)) is just some arbitrary point")
    }
    

    例二:所有的正數(shù)相加

    let numbers = [-1,2,3,-10,20]
    var sum = 0
    for num in numbers where num > 0 {
    
       sum += num
    }
    print("最后正數(shù)的和=\(sum)")
    

    提示:where 用來過濾 負(fù)數(shù)

  • 1.11、標(biāo)簽語(yǔ)句

    outer: for i in 1...4{
    
       for k in 1...4 {
      
          if k == 3 {
              continue outer
          }
          if i == 3 {
              break outer
          }
          print("i=\(i) k=\(k)")
       }
    }
    

二窥妇、函數(shù)

  • 2.1舷胜、函數(shù)的定義:是一組代碼的組合,因此函數(shù)也被稱為完成特殊功能的代碼塊活翩。函數(shù)三要素:函數(shù)名烹骨、參數(shù)、返回值材泄。

    • 有返回值沮焕,有參數(shù)

      func pi()->Double{
          return 3.14
      }
      print(pi())
      
      func sum(num1:Int,num2:Int)->Int{
          return num1 + num2
      }
      print(sum(num1: 1, num2: 3))
      

      提示:形參默認(rèn)是 let,也只能是 let

    • 無返回值拉宗,無參數(shù)峦树;下面的幾種 無返回值表達(dá)的意思是一樣的

      func sayHello()->Void{
         print("Hello")
      }
      
      func sayHello()->(){
         print("Hello")
      }
      
      func sayHello(){
         print("Hello")
      }
      
  • 2.2、函數(shù)的隱式返回

    func sum(num1:Int,num2:Int) -> Int{
         num1 + num2
    }
    sum(num1: 1, num2: 3)
    

    提示:如果整個(gè)函數(shù)的整體是一個(gè)單一的表達(dá)式簿废,那么函數(shù)會(huì)隱式返回這個(gè)表達(dá)式

  • 2.3空入、返回元組 和 實(shí)現(xiàn)多值返回

    func calculate(v1: Int,v2:Int) -> (sum:Int,difference:Int,average:Int){
    
         let sum = v1 + v2
         return (sum,v1-v2,sum>>1)
    }
    
    let result = calculate(v1: 20, v2: 10)
    result.sum   // 和 
    result.difference  // 差 : 10
    result.average   // 二進(jìn)制右移 是 平均值 15
    

    提示:sum>>1 代表值的二進(jìn)制數(shù) 右移 求平均值

  • 2.4、函數(shù)的文檔注釋 參考蘋果的鏈接

    /// 求和 【概述】
    ///
    /// 將兩個(gè)整數(shù)相加 【更詳細(xì)的描述】
    ///
    /// - Parameter v1: 第 1 個(gè)整數(shù)
    /// - Parameter v2: 第 2 個(gè)整數(shù)
    /// - Returns : 兩個(gè)整數(shù)的和
    ///
    /// - Note:傳入兩個(gè)整數(shù)即可 【批注】族檬,有沒有什么特殊的用法
    ///
    func sum(_ v1:Int,_ v2:Int) -> Int{
        return v1 + v2
    }
    
    sum(10, 20)
    

    效果如下:


  • 2.5歪赢、參數(shù)標(biāo)簽

    • 可以修改參數(shù)標(biāo)簽

      func goToWork(at time:String){
      
           print("this time is \(time)")
      }
      
      goToWork(at: "08:00")
      

      打印結(jié)果:this time is 08:00

    • 可以使用下劃線 _ 省略參數(shù)標(biāo)簽

      func sum(_ v1:Int,_ v2:Int) -> Int{
          return v1 + v2
      }
      
      sum(10, 20)
      
  • 2.6、默認(rèn)參數(shù)值(Default Parameter Value)

    • 參數(shù)可以有默認(rèn)值

      func check(name:String = "noPerson",age:Int,job:String = "iOS"){
      
          print("名字=\(name) 年齡=\(age) 工作=\(job)")
      }
      
      check(name: "老大", age: 19, job: "iOS")
      check(name: "老二", age: 19)
      check(age: 10, job: "前端")
      check(age: 16)
      

      提示:只要是有默認(rèn)參數(shù)值的就可以不傳參數(shù)

      • C++的默認(rèn)參數(shù)值有個(gè)限制:必須從右往左設(shè)置单料。由于Swift擁有參數(shù)標(biāo)簽埋凯,因此并沒有此類限制

      • 但是在省略參數(shù)標(biāo)簽時(shí),需要特別注意扫尖,避免出錯(cuò)白对,如下
        這里的 two 不可以省略參數(shù)標(biāo)簽

        func test(_ one:Int = 10,two:Int,_ three:Int = 20){
        
            print("打印 one = \(one) two = \(two) three = \(three)")
        }
        
        test(two: 9)
        
  • 2.7、可變參數(shù)(Variadic Parameter)

    func sum(_ numbers: Int...) -> Int {
    
       var total = 0
       for i in numbers {
           total += I
       }
       return total
    }
    
    sum(1,2,3)
    

    提示:一個(gè)函數(shù) 最多只能有1個(gè) 可變參數(shù)换怖;緊跟在可變參數(shù)后面的參數(shù)不能省略參數(shù)標(biāo)簽甩恼,如下

    func test(_ numbers:Int...,string:String,_ other:String){
    
    }
    
    test(1,2,3, string: "iOS", "Rose")
    

    參數(shù) string 標(biāo)簽不能省略

  • 2.8、Swift 自帶的 print 函數(shù)

    /// - Parameters:
    ///   - items: Zero or more items to print.
    ///   - separator: A string to print between each item. The default is a single
    ///     space (`" "`).
    ///   - terminator: The string to print after all items have been printed. The
    ///     default is a newline (`"\n"`).
    public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
    

    分析: 第一個(gè)參數(shù)是要打印的值沉颂,第二個(gè)參數(shù)是:連接第一個(gè)參數(shù)值的 字符条摸,第三個(gè)參數(shù)是:默認(rèn)是 \n 換行,如下例子

    print(1,2,3,4,5)
    print(1,2,3, separator: "_")
    print(1,2,3, separator: "_", terminator: "")
    print("哈哈")
    

    打印結(jié)果是: 最后一行不換行铸屉,因?yàn)?"\n" 被用 "" 取代了

    1 2 3 4 5
    1_2_3
    1_2_3哈哈
    
  • 2.9钉蒲、輸入輸出參數(shù) (In-Out Parameter)
    可以用 inout 定義一個(gè)輸入輸出函數(shù):可以在函數(shù)內(nèi)部修改外部實(shí)參的值

    func swapValues(_ v1:inout Int,_ v2:inout Int){
    
        let tem = v1
        v1 = v2
        v2 = tem
    }
    
    var num1 = 10
    var num2 = 20
    swapValues(&num1, &num2)
    
    print(num1,num2)
    

    打印結(jié)果:20 10

    • 提示:下面的函數(shù)與上面的等價(jià):傳進(jìn)去的是 內(nèi)存地址,所以可以修改其外部參數(shù)的值

      func swapValues(_ v1:inout Int,_ v2:inout Int){
      
         (v1,v2) = (v2,v1)
      }
      
    • 可變參數(shù)不能標(biāo)記為 inout

    • 輸入輸出參數(shù)不能有默認(rèn)值

    • 輸入輸出參數(shù)不能傳入常量(let)彻坛、字面量作為實(shí)參顷啼。也就是可以被多次賦值的 變量

    • inout 參數(shù)的本質(zhì)是地址傳遞 (引用傳遞)

  • 2.10踏枣、函數(shù)重載 (Function Overload)
    規(guī)則:函數(shù)名相同
    參數(shù)個(gè)數(shù)不同 || 參數(shù)類型不同 || 參數(shù)標(biāo)簽不同

    func sum(v1:Int,v2:Int) -> Int{
       return v1 + v2
    }
    

    參數(shù)個(gè)數(shù)不同

    func sum(v1:Int,v2:Int,v3:Int) -> Int{
        return v1 + v2
    }
    

    參數(shù)類型不同

    func sum(v1:Int,v2:Double) -> Double{
       return Double(v1) + v2
    }
    
    func sum(v1:Double,v2:Int) -> Double{
       return v1 + Double(v2)
    }
    

    參數(shù)標(biāo)簽不同

    func sum(_ v1:Int,_ v2:Int) -> Int{
       return v1 + v2
    }
    
    func sum(a:Int,b:Int) -> Int{
       return a + b
    }
    
    • 函數(shù)重載注意點(diǎn)一: 返回值類型 與 函數(shù)重載 無關(guān)

      func sum(a:Int,b:Int) -> Int{
          return a + b
      }
      
      func sum(a:Int,b:Int) {
      
      }
      
      sum(a: 1, b: 2)
      
    • 函數(shù)重載注意點(diǎn)二:默認(rèn)參數(shù)值和函數(shù)重載一起使用產(chǎn)生二義性時(shí),編譯器并不會(huì)報(bào)錯(cuò)(在 C++ 中會(huì)報(bào)錯(cuò))

      func sum(a:Int,b:Int) -> Int {
           return a + b
      }
      
      func sum(a:Int,b:Int,c:Int = 10) -> Int {
          return a + b + c
      }
      // 會(huì)調(diào)用 sum(a:Int,b:Int)钙蒙,這樣不太好茵瀑,還不如編譯器報(bào)錯(cuò)
      sum(a: 1, b: 2)
      
    • 函數(shù)重載注意點(diǎn)三:可變參數(shù),省略參數(shù)標(biāo)簽仪搔,函數(shù)重載一起使用產(chǎn)生二義性時(shí)瘾婿,編譯器有可能會(huì)報(bào)錯(cuò)

      func sum(a:Int,b:Int) -> Int{
          return a + b
      }
      
      func sum(_ a:Int,_ b:Int) -> Int {
          return a + b
      }
      
      func sum(_ numbers: Int...)->Int{
      
          var total = 0
          for i in numbers {
              total += I
          }
          return total
      }
      

      調(diào)用 sum(1,2) 報(bào)錯(cuò):Ambiguous use of 'sum'

  • 2.11蜻牢、內(nèi)聯(lián)函數(shù)(Inline function)

    • 如果開啟了編譯器優(yōu)化(Release模式默認(rèn)會(huì)開啟優(yōu)化)烤咧,編譯器會(huì)默認(rèn)將某些函數(shù)變成內(nèi)聯(lián)函數(shù)
      • 將函數(shù)調(diào)用展開成函數(shù)體

      將函數(shù)調(diào)用展開成函數(shù)體

      不會(huì)被內(nèi)聯(lián)的函數(shù):函數(shù)體比較長(zhǎng)、包含遞歸調(diào)用抢呆、包含動(dòng)態(tài)派發(fā)......

  • 2.12煮嫌、函數(shù)類型:每一個(gè)函數(shù)都是有類型的,函數(shù)的類型由:形式參數(shù)類型抱虐,返回值類型組成

    • 例子一:無參數(shù)無返回值

      func test() {}
      
    • 例子二:有參數(shù)有返回值

      func test(a: Int, b: Int) -> Int {
         return a + b
      }
      
    • 例子三:調(diào)用的時(shí)候不需要傳參數(shù)標(biāo)簽

      func test(_ a: Int ,_ b: Int) -> Int {
          return a + b
      }
      test(2,3)  // 調(diào)用的時(shí)候不需要傳參數(shù)標(biāo)簽
      
  • 2.13昌阿、函數(shù)類型作為函數(shù)參數(shù)

    func sum(a: Int, b: Int) -> Int{
        return a + b
    }
    func difference(a:Int,b:Int) -> Int{
        return a - b
    }
    func printResult(_ mathFn:(Int,Int)->Int,_ a:Int,_ b:Int){
        print("result=\(mathFn(a,b))")
    }
    
    printResult(sum, 5, 2)  // 打印結(jié)果:result=7
    printResult(difference, 5, 2) // 打印結(jié)果:result=3
    
  • 2.14、函數(shù)類型作為函數(shù)返回值

    func next(_ input: Int) -> Int {
        return input + 1
    }
    
    func previous(_ input: Int) -> Int {
        return input - 1
    }
    
    func forward(_ forward: Bool) -> (Int) -> Int {
        return forward ? next:previous
    }
    
    print(forward(true)(3))  //  結(jié)果:4
    print(forward(false)(3))  //  結(jié)果:2
    

    提示:返回值是函數(shù)的函數(shù)恳邀,叫做高階函數(shù)(Height-Order Function)

  • 2.15懦冰、typealias: 用來給類型起別名

    typealias Byte = Int8
    typealias Short = Int16
    typealias Long = Int64
    

    如下:

    typealias Date = (year:Int,month:Int,day:Int)
    
    func test(_ date:Date){
    
        print(date.year,date.month,date.day)
    }
    
    test((2019,6,19))
    

    例二:(重點(diǎn)????????????????????)

    typealias IntFn = (Int,Int) -> Int
    
    func difference(v1:Int,v2:Int)->Int{
         return v1-v2
    }
    let fn:IntFn = difference
    
    fn(20,10)
    
    func setFn(_ fn:IntFn){}
    setFn(difference)
    
    func getFn() -> IntFn{
    
        return difference
    }
    
  • 2.16、嵌套函數(shù): 將函數(shù)定義在函數(shù)的內(nèi)部

    func forward(_ forward:Bool)->(Int)->Int{
    
        func next(_ input:Int)->Int{
      
             return input + 1
        }
    
        func previous(_ input:Int)->Int{
      
             return input - 1
        }
    
        return forward ? next:previous
    }
    
    forward(true)(3)  // 4
    forward(false)(3) // 2
    

三谣沸、枚舉

  • 3.1刷钢、枚舉的基本用法

    enum Direction {
        case north
        case south
        case east
        case west
    }
    
    enum Direction {
        case north,south,east,west
    }
    

    使用如下:

    var dircetion = Direction.north
    dircetion = Direction.west
    dircetion = .south
      
    print("dircetion=\(dircetion)")
    
    let dir = Direction.north
      
    switch dir {
    case .north:
          print("north")
    case .south:
          print("south")
    case .east:
          print("east")
    case .west:
          print("west")
    }
    
  • 3.2、關(guān)聯(lián)值(Associated Values)

    • 有時(shí)會(huì)將枚舉的成員值跟其他類型的關(guān)聯(lián)存儲(chǔ)在一起乳附,會(huì)非常有用

      enum Score {
          case points(Int)
          case grade(Character) 
      }
      
      var source = Score.points(96)
      source = .grade("A")
      
      switch source {
      case let .points(i):
         print(i,"points")
      case let .grade(i):
        print("grade",i)
      }
      

      打印結(jié)果:grade A

    • 下面代碼必要的時(shí)候 let 可以改為 var

       enum Date{
      
           case digit(year:Int,month:Int,day:Int)
           case string(String)
       }
      
       var date = Date.digit(year:2019,month:6,day:21)
       date = .string("2019-6-21")
      
       switch date {
       case .digit(let year,let month,let day):
            print(year,month,day)
       case let .string(value):
            print(value)
       }
      

      打印結(jié)果:2019-6-21

    • 關(guān)聯(lián)值舉例


      關(guān)聯(lián)值手勢(shì)舉例
      enum Password{
      
         case number(Int,Int,Int,Int)
         case gesture(String)
      }
      
      var pwd = Password.number(3,5,7,8)
      pwd = .gesture("12368")
      
      switch pwd {
      case let .number(n1,n2,n3,n4):
          print("number is \(n1) \(n2) \(n3) \(n4)")
      case let .gesture(str):
          print("gesture is",str)
      }
      

      打印結(jié)果:gesture is 12368

  • 3.3内地、原始值 (Raw Values):枚舉成員可以使用相同類型的默認(rèn)值預(yù)先關(guān)聯(lián),這個(gè)默認(rèn)值叫做:原始值

    enum PlayingCards : Character{
    
        case A = "a"
        case B = "b"
        case C = "c"
        case D = "d"
    }
    
    var suit = PlayingCards.A
    
    print(suit)   // A
    print(suit.rawValue) // a
    print(PlayingCards.D.rawValue) // d
    
    enum Grade : String{
    
       case perfect = "A"
       case great = "B"
       case good = "C"
       case bad = "D"
    }
    
    print(Grade.perfect.rawValue)   // A
    print(Grade.great.rawValue)     // B
    print(Grade.good.rawValue)      // C
    print(Grade.bad.rawValue)       // D
    
  • 3.4赋除、隱式原始值 (Implicitly Assignd RawValues):如果枚舉的原始類型是Int阱缓、String 類型,Swift會(huì)自動(dòng)分配原始值

    • String 類型

      enum Direction {
           case north,south,east,west
      }
      print(Direction. north) // north
      print(Direction. north.rawValue) // north
      

      等價(jià)于

      enum Direction: String {
         case north =  "north"
         case south =  "south"
         case east =  "east"
         case west =  "west"
      }
      
    • Int 類型

      enum Season:Int{
      
         case spring,summer,autumn,winter
      }
      
      print(Season.spring.rawValue)   // 0
      print(Season.summer.rawValue)  // 1
      print(Season.autumn.rawValue)  // 2
      print(Season.winter.rawValue)  // 3
      
    • Int 類型設(shè)置了默認(rèn)原始值举农,設(shè)置了值之后 Swift會(huì)自動(dòng)遞增原始值

      enum Season:Int{
      
         case spring = 2,summer,autumn = 5,winter
      }
      
      print(Season.spring.rawValue)   // 2
      print(Season.summer.rawValue)  // 3
      print(Season.autumn.rawValue)  // 5
      print(Season.winter.rawValue)  // 6
      
  • 3.5荆针、遞歸枚舉 (Recursive Enumeration)

    enmu ArithExpr{
        case number(Int)
        indirect case sum(ArithExpr,ArithExpr)
        indirect case difference(ArithExpr,ArithExpr)
    }
    
    let five = ArithExpr.number(5)
    let four = ArithExpr.number(4)
    let two = ArithExpr.number(2)
    let sum = ArithExpr.sum(five,four)
    let difference = ArithExpr.difference(sum,two)
    
    func calculate(_ expr:ArithExpr) -> Int{
    
        switch expr {
        case let .number(value):
           return value
        case let .sum(left,right):
           return calculate(left) + calculate(right)
        case let .difference(left,right):
           return calculate(left) - calculate(right)
        }
    }
    
    calculate(difference)
    

    提示:使用 indirect 關(guān)鍵字修飾的枚舉值表示這個(gè)枚舉是可以遞歸的,即此枚舉值中的相關(guān)值使用其枚舉類型本身颁糟。

  • 3.7航背、MemoryLayout: 獲取數(shù)據(jù)類型占用的內(nèi)存大小

    enum Password{
    
        case number(Int,Int,Int,Int)  // 32 字節(jié)
        case other  // 1 個(gè)字節(jié)就搞定了
    }
    
    MemoryLayout<Password>.stride   // 40 分配占用的內(nèi)存空間大小
    MemoryLayout<Password>.size  // 33 實(shí)際用到的空間大小
    MemoryLayout<Password>.alignment  // 8 對(duì)齊參數(shù)
    
    var password = Password.number(2,3,4,5)
    password = .other
    
    MemoryLayout.stride(ofValue:password)   // 40
    MemoryLayout.size(ofValue:password)  // 33
    MemoryLayout.alignment(ofValue:password)  // 8
    
    • 提示1:stride:范圍 與 size 的區(qū)別
      size: 分配占用的內(nèi)存空間大小
      stride: 實(shí)際用到的空間大小
      內(nèi)存對(duì)齊是 8個(gè)字節(jié) ,所以上面是 32+1 = 40
    • 提示2:N個(gè)字節(jié)存儲(chǔ)關(guān)聯(lián)值(N取內(nèi)存最大的關(guān)聯(lián)值)滚停,比如number(Int,Int,Int,Int)就是 4*8=32 里面的元素是關(guān)聯(lián)值沃粗,1個(gè)字節(jié)用來存儲(chǔ)成員值(也就是case的個(gè)數(shù))
  • 3.8、枚舉拓展

    • 拓展一:枚舉的關(guān)聯(lián)值(3.2) 和 默認(rèn)原始值(3.3) 的區(qū)別
      分析:枚舉的關(guān)聯(lián)值 的值 是寫到枚舉的內(nèi)存中的键畴,而枚舉的原始值是固定死的最盅,沒有寫入枚舉的內(nèi)存中
      舉例如下:

      enum Season:Int{
      
           case spring,summer,autumn,winter
      }
      
      MemoryLayout<Season>.stride   // 1
      MemoryLayout<Season>.size  // 1
      MemoryLayout<Season>.alignment  // 1
      
    • 拓展二:思考下面枚舉變量的內(nèi)存布局

      enum TestNum {
         case test1,test2,test3,test4
      }
      
      print( MemoryLayout<TestNum>.stride) // 1 分配占用的內(nèi)存空間大小
      print(MemoryLayout<TestNum>.size) // 1 實(shí)際用到的空間大小
      print(MemoryLayout<TestNum>.alignment) // 1 對(duì)齊參數(shù)
      
      • 提示1:直接查看內(nèi)存布局


        內(nèi)存布局的展示
      • 提示2:我們還可以在Debug -> Debug Workflow -> View Memory 手動(dòng)輸入內(nèi)存地址來查看內(nèi)存布局突雪,如下


        在Debug -> Debug Workflow -> View Memory 手動(dòng)輸入內(nèi)存地址來查看內(nèi)存布局

      分析: 用來窺探Swift內(nèi)存的小工具

      var t = TestNum.test1
      print( Mems.ptr(ofVal: &t))
      t = .test2
      t = .test3
      t = .test4
      
      • 上面是采取一個(gè)字節(jié)來存儲(chǔ)枚舉變量的數(shù)據(jù),一個(gè)字節(jié) 00 用來存儲(chǔ) test1涡贱、一個(gè)字節(jié) 01 用來存儲(chǔ) test2咏删、一個(gè)字節(jié) 02 用來存儲(chǔ) test3、一個(gè)字節(jié) 03 用來存儲(chǔ) test4问词,其實(shí)也就是來區(qū)分成員變量的值
      • 按照上面的一個(gè)字節(jié)來區(qū)分的話督函,一個(gè)字節(jié)的范圍是 0x00~0xFF,最大也就是 256,每一個(gè)case也就是一個(gè)成員變量激挪,其實(shí)case test1,test2,test3,test4 相當(dāng)于四個(gè)case
    • 拓展三:看下面一個(gè)復(fù)雜的枚舉

      enum TestNum {
        case test1(Int,Int,Int)
        case test2(Int,Int)
        case test3(Int)
        case test4(Bool)
        case test5
      }
      
      print(MemoryLayout<TestNum>.size)  //  25分配的內(nèi)存大小
      print(MemoryLayout<TestNum>.stride) // 32 實(shí)際使用的內(nèi)存大小
      print(MemoryLayout<TestNum>.alignment)  // 8 內(nèi)存對(duì)齊的字節(jié)數(shù)
      

      分析:分配內(nèi)存的規(guī)則:如果有多個(gè)case,那么必有一個(gè)字節(jié)存儲(chǔ)來區(qū)分成員變量case辰狡,再看case關(guān)聯(lián)值最多的那個(gè)有多少個(gè)關(guān)聯(lián)值,N個(gè)字節(jié)存儲(chǔ)關(guān)聯(lián)值(N取內(nèi)存最大的關(guān)聯(lián)值)垄分,比如number(Int,Int,Int)就是 3*8=24 里面的元素是關(guān)聯(lián)值宛篇,1個(gè)字節(jié)用來存儲(chǔ)成員值(也就是case的個(gè)數(shù)),那么分配的內(nèi)存是 32薄湿,實(shí)際用了 24+1= 25

    • 拓展四:看下面一個(gè)有意的的枚舉

      enum TestNum {
          case test1(Int,Int,Bool,Bool)
          case test2(Int,Int)
      }
      
      print(MemoryLayout<TestNum>.size)  //  實(shí)際使用的內(nèi)存大小 18
      print(MemoryLayout<TestNum>.stride) // 分配的內(nèi)存大小 24
      print(MemoryLayout<TestNum>.alignment) // 內(nèi)存對(duì)齊的字節(jié)數(shù) 8
      

      分析:8+8+最后一個(gè)Bool【1(第一個(gè)bool)+1(區(qū)別成員變量) 】= 17 這是編譯器的進(jìn)一步優(yōu)化叫倍,它把case標(biāo)志放在最后一個(gè)Bool字節(jié)里去了,相當(dāng)于最后一個(gè)Bool豺瘤,它的那個(gè)字節(jié)里面包含了case成員信息吆倦。因?yàn)锽ool類型只有2種取值,true是1坐求,false是0蚕泽,只會(huì)用到1個(gè)二進(jìn)制位,所以Bool的1個(gè)字節(jié)還是有多余空間的瞻赶,如果是Int這些赛糟,就有可能要把它自己的8個(gè)字節(jié)都用完。所以無法拿來放case砸逊,比如0xFF FF FF FF FF FF FF FF璧南,占滿了8字節(jié),而Bool师逸,你的8個(gè)二進(jìn)制位司倚,不管存儲(chǔ)true還是false,都只需要用到1位

    • 拓展五:沒有關(guān)聯(lián)值

      enum TestNum {
           case test1,test2,test3,test4
      }
      
      print(MemoryLayout<TestNum>.size)  //  實(shí)際使用的內(nèi)存大小 1
      print(MemoryLayout<TestNum>.stride) // 分配的內(nèi)存大小 1
      print(MemoryLayout<TestNum>.alignment) //  內(nèi)存對(duì)齊的字節(jié)數(shù) 1
      

      分析:這里的 1 僅僅是為了區(qū)分 成員變量使用的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末篓像,一起剝皮案震驚了整個(gè)濱河市动知,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌员辩,老刑警劉巖盒粮,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異奠滑,居然都是意外死亡丹皱,警方通過查閱死者的電腦和手機(jī)妒穴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摊崭,“玉大人讼油,你說我怎么就攤上這事∧佤ぃ” “怎么了矮台?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)根时。 經(jīng)常有香客問我瘦赫,道長(zhǎng),這世上最難降的妖魔是什么啸箫? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任耸彪,我火速辦了婚禮伞芹,結(jié)果婚禮上忘苛,老公的妹妹穿的比我還像新娘。我一直安慰自己唱较,他們只是感情好扎唾,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著南缓,像睡著了一般胸遇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汉形,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天纸镊,我揣著相機(jī)與錄音,去河邊找鬼概疆。 笑死逗威,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岔冀。 我是一名探鬼主播凯旭,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼使套!你這毒婦竟也來了罐呼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤侦高,失蹤者是張志新(化名)和其女友劉穎嫉柴,沒想到半個(gè)月后僵闯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仁期,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胯陋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年厅须,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片危尿。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呐萌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谊娇,到底是詐尸還是另有隱情肺孤,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布济欢,位于F島的核電站赠堵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏法褥。R本人自食惡果不足惜茫叭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望半等。 院中可真熱鬧揍愁,春花似錦、人聲如沸杀饵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)切距。三九已至朽缎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谜悟,已是汗流浹背话肖。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葡幸,地道東北人最筒。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像礼患,于是被迫代替她去往敵國(guó)和親是钥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容