《Advanced Swift》第三章 可选值:读书笔记 一、哨岗值 二、通过枚举解决魔法数的问题 三、可选值概览 四、强制解包的时机 五、隐式解包可选值

一、哨岗值

int ch;
while ((ch = getchar()) != EOF) {
  printf("Read character %c\n", ch);
}
printf("Reached end-of-file\n");

        像上面的EOF,这种东西被叫做哨岗值,其广泛存在与c、C++、java之中。其存在有其合理性,但是却很不合理,其混淆了正常值、需要一些潜规则知识等等,不合理因素。
        Tony Hoare 在 1965 年设计了 null 引用,他对此设计表示痛心疾首,并将这个问题称为 “价值 十亿美元的错误”。

二、通过枚举解决魔法数的问题

        上文中的哨岗值其实就是一个魔法数,大家都知道这是不好的。所以在Swift中,引入了可选值(通过枚举、关联值、泛型来实现)。

// 可选值的核心代码
enum Optional<Wrapped> {
  case none
  case some(Wrapped)
}

// 由于可选值遵循了ExpressibleByNilLiteral协议,所以可是用nil来代替none

三、可选值概览


var array = ["one", "two", "three", "four"]
// 检查可选值是否为 nil,如果不是 nil,便会解包可选值
// idx 的类型就是 Int (而不再是可 选值),并且 idx 也只在这个 if let 语句的作用域中有效
if let idx = array.firstIndex(of: "four") {
  array.remove(at: idx)
}

// while let 语句和 if let 非常相似,它表示当一个条件返回 nil 时便终止循环。
while let line = readLine() {
  print(line)
}

// 为了解决if、while、switch解包后值的作用域问题,引入了guard语句
// 可选链
// ?? 运算符

// 在字符串插值中使用可选值
let bodyTemperature: Double? = 37.0
let bloodGlucose: Double? = nil
print(bodyTemperature) // Optional(37.0)
// 警告:表达式被隐式强制从 'Double?' 转换为 Any
print("Blood glucose level: \(bloodGlucose)") // Blood glucose level: nil // 警告:字符串插值将使用调试时的可选值描述,
// 请确认这确实是你想要做的。

infix operator ???: NilCoalescingPrecedence
public func ???<T>(optional: T?, defaultValue: @autoclosure () -> String) -> String
{
switch optional {
  case let value?: return String(describing: value)
  case nil: return defaultValue()
  }
}

print("Body temperature: \(bodyTemperature ??? "n/a")") // Body temperature: 37.0
print("Blood glucose level: \(bloodGlucose ??? "n/a")")
// Blood glucose level: n/a

可选值提供了map、flatMap、compactMap方法。

四、强制解包的时机

        当你能确定你的某个值不可能是 nil 时可以使用叹号,你应当会希望如果它意外是 nil 的话,程序应当直接挂掉。

// 提供!!运算符,用于强制解包时,能够输出友好的信息
infix operator !!
func !! <T>(wrapped: T?, failureText: @autoclosure () -> String) -> T { ifletx=wrapped{returnx}
fatalError(failureText())
}

let s = "foo"
let i = Int(s) !! "Expecting integer, got \"\(s)\""

五、隐式解包可选值

        强制解包会引发崩溃,但是隐式解包与强制解包类似,但是它依然存在。

  • 在使用从nib获取的outlet时,此时一般使用隐式解包
  • 为了与OC代码兼容
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章