LoginSignup
13
10

⚡️令和 5 年最新版⚡️ Swift コードの書き方をアップデートする

Last updated at Posted at 2023-12-07

この記事は セーフィー株式会社 Advent Calendar 2023 7 日目の記事です。

はじめに

今年は Swift 5.9 が発表されました。

Macros
実装も AST も使いどころも難しい😣

Observation
iOS 17.0+ だとプロダクション投入はちょっと。。😓

そんな我々のために、 Swift 5.9 を含むここ 1 〜 2 年ほどの Swift アップデートで可能となった、明日からでも使える Swift コードの書き方をいくつか紹介します。

  • 個人的によく使う / よく使われるであろうもの
  • Swift 5.9 (Xcode 15.0) 以降なら Deployment Target を気にせず利用できる

といったものを中心にまとめました。

Optional Binding

if let hoge = hoge

if let の shorthand 記法が導入されたため、同名の変数名で unwrap されたものを簡単に用意できるようになりました。

🙁 これまで
let hoge: Hoge? = ...
if let hoge = hoge {
  // unwrap された `hoge` を利用可能
}
🙂 これから
let hoge: Hoge? = ...
if let hoge {
  // unwrap された `hoge` を利用可能
}

// 複数個も対応
let fuga: Fuga? = ...
if let hoge, let fuga {
  // unwrap された `hoge`, `fuga` を利用可能
}

また後述するのですが、 guard let や、 while let といった各種 Optional Binding でも同様の記述ができるようになっています。

対応バージョン、関連 Proposal は以下の通りです。

guard let self = self else { return } ...

つい手癖で書いてしまう guard let self = self else { return } ... の処理ですが、段階を踏んでかなり簡潔に記述できるようになりました。

🙁 これまで
hoge.callback = { [weak self] in
  guard let `self` = self else { return }

  self.fuga()
}
🙂 これから
hoge.callback = { [weak self] in
  guard let self else { return }  // shorthand 記法

  fuga()  // `self.` を省略可能
}

だいぶ以前は guard let self = self ができてしまうのはバグといったような話もあったのですが、複数の Proposal を通して、上述のように Swift らしいシュッっとしたコードに収まるようになりました。

関連する Proposal としては、

  1. guard let self = self が正式に OK になる
  2. guard let self の shorthand 記法導入 (前セクションの通り)
  3. self. が省略可能となる

で、 Swift 5.8 で一応の完成を見ています。

if 式 / switch 式

制限はありますが、 if / switch が式 (expression) としても扱えるようになりました。

具体的に何が嬉しいかというと、以下のような書き方ができるようになります。

🙁 これまで
func hoge(type: MetaType) {
  let evaluation: String
  
  switch type {
    case .hoge:
      evaluation = "good!"
    case .fuga:
      evaluation = "not bad."
    case .piyo:
      evaluation = "very bad..."
  }
  ...
}
🙂 これから
func hoge(type: MetaType) {
  let evaluation: String = switch type {
    case .hoge:
      "good!"
    case .fuga:
      "not bad."
    case .piyo:
      "very bad..."
  }
  ...
}

これまでもコンパイラレベルで変数初期化時の網羅性チェックにてエラーとしてくれていたのですが、より直感的な表現での記述が可能となりました。

また、 Proposal での動機の一つとしても挙げられているのですが、 Kotlin / Android Studio でよく suggest される return の lift out についても可能となりました。

🙁 これまで
func hoge(type: MetaType) -> String {
  if type == .hoge {
    return "hoge" 
  } else if type == .fuga {
    return "fuga"
  } else {
    return "unknown"
  }
}
🙂 これから
func hoge(type: MetaType) -> String {
  return if type == .hoge {
    "hoge" 
  } else if type == .fuga {
    "fuga"
  } else {
    "unknown"
  }
}

注意点として、

Each branch of the if, or each case of the switch, must be a single expression.

であることが求められます。

このため、複数行に渡る複雑な処理やログ出力を仕込むために 1 行追加するといった場合への適用が難しく、他言語での if / switch 式の感覚とは異なる部分があります。

対応バージョン、関連 Proposal は以下の通りです。

extension Array where Element = ... { }

配列で表現されるモデルに対して、 extension Arrayextension Sequence 等で便利メソッドを生やすといったことがあるかと思います。

この際、 where Element == ... でやや冗長な記述が発生するのですが、これについても直感的な記述が可能となりました。

🙁 これまで
extension Array where Element == Hoge {
  func fuga() -> String {
    ...
  }
}
🙂 これから
extension Array<Hoge> {
  func fuga() -> String {
    ...
  }
}

対応バージョン、関連 Proposal は以下の通りです。

ViewBuilder に並べられる View の数

SwiftUI に入門すると必ずぶつかる View が 10 個まで並べられない問題が解消されました。

🙁 これまで
var body: some View {
  VStack {
    Text("01")
    Text("02")
    Text("02")
    Text("04")
    Text("05")
    Text("06")
    Text("07")
    Text("08")
    Text("09")
    Group {  // `Group` でラップするワークアラウンド
      Text("10")
      Text("11")
    }
  }
}
🙂 これから
var body: some View {
  VStack {
    Text("01")
    Text("02")
    Text("02")
    Text("04")
    Text("05")
    Text("06")
    Text("07")
    Text("08")
    Text("09")
    Text("10")
    Text("11")
  }
}

以前は、

で宣言されていた ViewBuilder.buildBlock の処理が

buildBlock(_:)

でまとまってくれたためで、 Swift 5.9 で導入された Value and Type Parameter Packs が寄与しています。

よくある iOS 17.0+ な 新 API への置き換えではないため、 Deployment Target を気にせず利用できます。

対応バージョン、関連 Proposal は以下の通りです。

参考記事

13
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10