站在彙編角度深入瞭解 Swift(三)

小星星_ios發表於2020-04-03

列舉

  • 基本用法
enum Direction {
    case north, south, east, west
}
複製程式碼
  • 關聯值
    • 有時會將列舉的成員值跟其他型別的關聯儲存在一起,會非常有用
enum Score {
    case points(Int)
    case grade(Character)
}
var score = Score.points(96)
score = .grade("A")
switch score {
    case let .points(i):
    print("points", i)
    case let .grade(i):
    print("grade", i)
}
複製程式碼
比如在使用者密碼的設定
enum Password {
    case number(Int, Int, Int, Int)
    case gesture(String) // 如果是手勢,你不知道他到底是怎麼畫的,畫了幾個,用 number 存會麻煩一點
}
複製程式碼
  • 原始值(rawValue)
    • 列舉成員可以使用相同型別的預設值預先關聯,這個預設值叫做:原始值
    • 隱式原始值
      • 如果列舉的原始值是 Int、String,Swift 會自動分配原始值
    • 遞迴列舉
enum Grade: String {
    case perfect = "A"
    case great = "B"
    case good = "C"
    case bad = "D"
}
複製程式碼
遞迴列舉:
enum ArithExpr {
    case number(Int)
    indirect case sum(ArithExpr, ArithExpr)
    indirect case difference(ArithExpr, ArithExpr)
}
複製程式碼

MemoryLayout

  • 可以使用 MemoryLayout 獲取資料型別佔用的記憶體大小
// 型別實際使用的大小
MemoryLayout<Int>.size
// 
// 型別分配的記憶體空間大小
MemoryLayout<Int>.stride
// 型別的記憶體對齊
MemoryLayout<Int>.alignment
let age = 10
MemoryLayout.size(ofValue: age)
MemoryLayout.stride(ofValue: age)
MemoryLayout.alignment(ofValue: age)
複製程式碼

可選項(Optional)

  • 可選項,一般也叫可選型別,它允許將值設定為 nil
  • 在型別名稱後面加個問號?來定義一個可選項
  • 可選項繫結
    • 可以使用可選項繫結來判斷可選項是否包含值
    • 如果包含就自動解包,把值賦值給一個臨時的常量或者變數,並返回 true,否則返加 false
if let number = Int("123") {
    
} else {
    
}
複製程式碼
  • 空合併運算子
    • a ?? b
    • a 是可選項
    • b 跟 a 的儲存型別必須相同,可以是可選,也可以是不可選
    • 如果 b 不是可選項,返回 a 時會自動解包(這一點要注意,就是返回值是不是可選主要看後面的是不是可選項)
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throw -> T?) rethrows -> T?
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throw -> T) rethrows -> T
複製程式碼
if let c = a ?? b { }
等於
if a != nil || b != nil { }
複製程式碼

guard 語句

  • 一般用來“提前退出”
  • 當使用 guard 語句進行可選項繫結時,繫結的常量,變數也能在外層作用域中使用
guard 條件 else {
    退出當前作用域
}
複製程式碼

隱式解包

  • 在某些情況下,可選項一旦敲定值之後,就會一直擁有值
  • 在這種情況下,可以去掉檢查,也不必每次訪問的時候都進行解包,因為它能確定每次訪問的時候都有值
  • 可以在型別後面加個感嘆號 ! 定義一個隱式解包的可選項
// 隱式解包的可選項
// 這個型別基本上沒啥用
var num1: Int! = 10
num1 = nil
print(num1)
這個地方發列印 nil,不會發生崩潰
複製程式碼

字串插值

  • 可選項在字串插值或者直接列印時,編譯器會發出警告
  • 至少有3種方法消除警告
var age: Int? = 10
// String interpolation produces a debug description for an optional value; did you mean to make this explicit?
print("My age is \(age)")

// 解決方式
print("My age is \(age!)")
print("My age is \(String(describing: age))")
print("My age is \(age ?? 0)")
複製程式碼

多重可選項

  • 可以利用 frame variable -R 檢視區別
var num1: Int? = nil 
var num2: Int?? = 10 
var num3: Int?? = nil

print(num2 == num3) // false
print(num1 == num3) // false
(num2 ?? 1) ?? 2 // 2
(num3 ?? 1) ?? 2 // 1

frame variable -R 變成了
(Swift.Optional<Swift.Int>) num1 = none {
  some = {
    _value = 0
  }
}
(Swift.Optional<Swift.Optional<Swift.Int>>) num2 = some {
  some = some {
    some = {
      _value = 10
    }
  }
}
(Swift.Optional<Swift.Optional<Swift.Int>>) num3 = none {
  some = some {
    some = {
      _value = 0
    }
  }
}
複製程式碼

相關文章