Swift 5 字串插值之美

SwiftGG翻譯組發表於2019-02-21

作者:Erica Sadun,原文連結,原文日期:2018-12-12 譯者:RocZhang;校對:numbbbbbpmst;定稿:Forelax

感謝提案 SE-0228,讓我們能夠精確控制字串插值的列印方式。感謝 Brent 帶給我們這個非常棒的功能。讓我來分享一些例子。

回想一下在我們要列印可選值的時候,會這樣寫:

"There's \(value1) and \(value2)"
複製程式碼

但這樣寫會立即得到一個警告:

Swift 5 字串插值之美

我們可以點選修復按鈕來消除這些警告,得到如下的程式碼。但我們仍然會看到一個類似於這樣的輸出:“There’s Optional(23) and nil”。

"There's \(String(describing: value1)) and \(String(describing: value2))"
複製程式碼

現在我們可以通過下面這種方式去掉輸出中的“Optional”,直接列印出“There’s 23 and nil”:

extension String.StringInterpolation {
  /// 提供 `Optional` 字串插值
  /// 而不必強制使用 `String(describing:)`
  public mutating func appendInterpolation(_ value: T?, default defaultValue: String) {
    if let value = value {
      appendInterpolation(value)
    } else {
      appendLiteral(defaultValue)
    }
  }
}

// There's 23 and nil
"There's \(value1, default: "nil") and \(value2, default: "nil")"
複製程式碼

我們也可以建立一組樣式,從而使可選值能夠保持一致的輸出展示方式:

extension String.StringInterpolation {
  /// 可選值插值樣式
  public enum OptionalStyle {
    /// 有值和沒有值兩種情況下都包含單詞 `Optional`
    case descriptive
    /// 有值和沒有值兩種情況下都去除單詞 `Optional`
    case stripped
    /// 使用系統的插值方式,在有值時包含單詞 `Optional`,沒有值時則不包含
    case `default`
  }

  /// 使用提供的 `optStyle` 樣式來插入可選值
  public mutating func appendInterpolation(_ value: T?, optStyle style: String.StringInterpolation.OptionalStyle) {
    switch style {
    // 有值和沒有值兩種情況下都包含單詞 `Optional`
    case .descriptive:
      if value == nil {
        appendLiteral("Optional(nil)")
      } else {
        appendLiteral(String(describing: value))
      }
    // 有值和沒有值兩種情況下都去除單詞 `Optional`
    case .stripped:
      if let value = value {
        appendInterpolation(value)
      } else {
        appendLiteral("nil")
      }
    // 使用系統的插值方式,在有值時包含單詞 `Optional`,沒有值時則不包含
    default:
      appendLiteral(String(describing: value))
    }
  }

  /// 使用 `stripped` 樣式來對可選值進行插值
  /// 有值和沒有值兩種情況下都省略單詞 `Optional`
  public mutating func appendInterpolation(describing value: T?) {
    appendInterpolation(value, optStyle: .stripped)
  }
}

// "There's Optional(23) and nil"
"There's \(value1, optStyle: .default) and \(value2, optStyle: .default)"

// "There's Optional(23) and Optional(nil)"
"There's \(value1, optStyle: .descriptive) and \(value2, optStyle: .descriptive)"

// "There's 23 and nil"
"There's \(describing: value1) and \(describing: value2)"
複製程式碼

插值不僅僅用於調整可選值的輸出方式,在其他方面也很有用。比如你想控制輸出是否帶有特定的字元,就不需要寫一個帶有空字串的三元表示式:

// 成功時包含(感謝 Nate Cook)
extension String.StringInterpolation {
  /// 只有 `condition` 的返回值為 `true` 才進行插值
  mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) {
    guard condition() else { return }
    appendLiteral(literal)
  }
}

// 舊寫法
"Cheese Sandwich \(isStarred ? "(*)" : "")"

// 新寫法
"Cheese Sandwich \(if: isStarred, "(*)")"
複製程式碼

我們還可以用字串插值來做更多有趣的事情。

本文由 SwiftGG 翻譯組翻譯,已經獲得作者翻譯授權,最新文章請訪問 swift.gg

相關文章