はじめに:Swift 6.2が目指す世界
Swift 6.2がついにやってきました。今回のアップデート、正直に言うとかなり大きいです。一番の目玉は並行処理(Concurrency)の大幅な簡素化。Swift 5.5でasync/awaitとアクターモデルが入ったときは「おお、未来が来た!」と思ったものですが、実際に使ってみると……難しかったですよね。
Sendable制約に引っかかる、アクター分離のルールがわからない、「このコードはどこで実行されてるの?」と頭を抱える。そんな経験、きっと多くの人にあるはずです。
Swift 6.2はそこに正面から切り込みました。「デフォルトで安全、必要なときだけ並行」というシンプルなアプローチです。さらに、InlineArrayやSpanといった新しいデータ型、weak letやRaw Identifiersなどの言語強化、Swift Testingの進化まで、盛りだくさんの内容になっています。
この記事では、Swift 6.2の主要な新機能をすべて、実践的なコード例つきで解説していきます。iOS、macOS、watchOS、tvOS、visionOS——どのプラットフォームで開発していても役立つ内容ですので、ぜひ最後まで読んでみてください。
並行処理の革新:もう難しくない
Swift 6.2の並行処理の変更を一言で表すなら、「シンプルなコードをシンプルなままに書ける」ようにするためのもの。それぞれ見ていきましょう。
デフォルトMainActor分離(SE-0466)
iOSアプリを書いていると、コードの大部分はメインスレッドで動くものです。UIの更新、ユーザーの操作処理、データバインディング——全部メインスレッドですよね。なのに、Swift 6.1までは@MainActorを至る所にペタペタ貼る必要がありました。
Swift 6.2では、モジュール全体のデフォルト分離をMainActorに設定できるようになりました。これが本当にありがたい。
// Package.swiftでの設定
.target(
name: "MyApp",
swiftSettings: [
.defaultIsolation(MainActor.self)
]
)
この設定を入れると、モジュール内のすべての型と関数がデフォルトでMainActorに分離されます。もう@MainActorを毎回書かなくていいんです。
// Swift 6.1まで:@MainActorを明示的に書く必要があった
@MainActor
class UserProfileViewModel: ObservableObject {
@Published var userName: String = ""
@Published var isLoading: Bool = false
func loadProfile() async {
isLoading = true
// ...
}
}
// Swift 6.2(defaultIsolation設定済み):アノテーション不要!
class UserProfileViewModel: ObservableObject {
@Published var userName: String = ""
@Published var isLoading: Bool = false
func loadProfile() async {
isLoading = true
// 自動的にMainActor上で実行される
}
}
SwiftUIアプリにとっては革命的な変更です。Viewモデル、データコントローラ、サービスクラスなど、UIに関連するほとんどの型で@MainActorを省略できます。バックグラウンドで実行したい処理だけに@concurrentを付ければOK。
nonisolated(nonsending)デフォルト(SE-0461)
Swift 6.1までは、nonisolated asyncな関数が自動的に呼び出し元のアクターから離れた別のコンテキストで実行されていました。これが大量のSendableエラーの元凶だったんですよね。
Swift 6.2では、nonisolated asyncな関数がデフォルトで呼び出し元のアクターコンテキストを継承するようになりました。MainActorから呼べば、そのままMainActor上で動きます。
class NetworkingClient {
// Swift 6.2:呼び出し元のアクター上で実行される
// → Sendableの境界を越えないのでエラーが減る
func fetchUserData() async throws -> UserData {
let url = URL(string: "https://api.example.com/user")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(UserData.self, from: data)
}
}
@MainActor
class ProfileController {
let client = NetworkingClient()
func refresh() async {
// fetchUserDataがMainActor上で実行される
// Sendable制約に引っかからない!
let data = try? await client.fetchUserData()
updateUI(with: data)
}
}
この変更だけで、今まで悩まされてきた「謎のSendableエラー」がかなり解消されるはずです。並行処理を始めたばかりの人が一番苦しんでいた部分が、ようやく改善されました。
@concurrent属性(SE-0461)
じゃあ、意図的にバックグラウンドで実行したい処理はどうするの? という疑問に答えるのが@concurrent属性です。
class ImageProcessor {
// 明示的にバックグラウンドで実行したい重い処理
@concurrent
nonisolated func applyFilters(to image: UIImage) async -> UIImage {
// メインスレッドをブロックしない
let filtered = await performHeavyImageProcessing(image)
return filtered
}
}
@MainActor
class PhotoEditor {
let processor = ImageProcessor()
func processCurrentPhoto() async {
let original = currentImage
// applyFiltersはバックグラウンドで実行される
let processed = await processor.applyFilters(to: original)
// ここはMainActorに戻る
displayImage(processed)
}
}
つまり、「並行処理はオプトイン」になったということ。デフォルトは直列実行で、@concurrentを付けたときだけ並行実行。コードの実行モデルが格段にわかりやすくなりました。
Task.immediate(SE-0472)
従来のTask { }はタスクをキューに入れるだけで、実際にいつ動くかはランタイム任せでした。地味に困ることがあったんですよね。
Swift 6.2のTask.immediateは、タスクを作って即座に実行を開始する新しいAPIです。
print("開始")
Task {
print("通常のTask") // 3番目に出力される
}
Task.immediate {
print("即時Task") // 2番目に出力される(最初のawaitまで即座に実行)
}
print("完了")
// 出力順序:
// 開始
// 即時Task
// 完了
// 通常のTask
Task.immediateのクロージャは、最初のawaitに達するまで同期的に実行されます。UIの即時更新や初期データの設定で「すぐに実行してほしい」場面にぴったりです。
タスクグループにも同じ仕組みが追加されています。
await withTaskGroup(of: String.self) { group in
// 通常の子タスク:キューに入れられてから実行
group.addTask { await fetchTitle() }
// 即時子タスク:すぐに実行開始
group.addImmediateTask { await fetchSubtitle() }
}
isolated deinit(SE-0371)
アクター分離されたクラスのdeinitで、安全にプロパティにアクセスできるようになりました。以前はdeinit内でアクター分離されたプロパティに触ると警告が出て、ちょっと面倒だったんですよね。
@MainActor
class StreamingConnection {
var isConnected: Bool = false
var connectionId: String?
isolated deinit {
// MainActor上で安全にアクセス可能
if isConnected {
print("接続 \(connectionId ?? "unknown") をクリーンアップ中...")
NotificationCenter.default.post(
name: .connectionClosed,
object: connectionId
)
}
}
}
グローバルアクター分離準拠(SE-0470)
プロトコル準拠をグローバルアクターに限定できるようになりました。「このプロトコル準拠はMainActorでしか使わない」という意図を型システムで表現できます。
@MainActor
class UserProfile: @MainActor Equatable {
var name: String
var email: String
static func == (lhs: UserProfile, rhs: UserProfile) -> Bool {
// MainActor上でのみ呼び出し可能
lhs.name == rhs.name && lhs.email == rhs.email
}
}
タスクの優先度エスカレーション(SE-0462)
実行中のタスクの優先度が変わったことを検出して、動的に対応できるようになりました。長時間のバッチ処理なんかで便利です。
func processLargeDataset() async throws {
try await withTaskPriorityEscalationHandler {
for chunk in dataset.chunks(ofCount: 1000) {
try Task.checkCancellation()
await processChunk(chunk)
}
} onPriorityEscalated: { oldPriority, newPriority in
print("優先度が \(oldPriority) から \(newPriority) にエスカレーション")
}
}
タスクの命名(SE-0469)
デバッグのとき、タスクに名前が付いていると本当に助かります。Swift 6.2では簡単に名前を付けられます。
await withTaskGroup(of: NewsSection.self) { group in
for section in sections {
group.addTask(name: "ニュースセクション: \(section.title)") {
try? await fetchSection(section)
}
}
for await result in group {
displaySection(result)
}
}
Instrumentsやデバッガでタスク一覧を見たとき、名前が付いていると捗りますよ。
Observations:@Observableの新しい監視方法(SE-0475)
Swift 5.9で入った@Observableマクロ、便利でしたよね。でもプロパティの変更をAsyncSequenceとして受け取る標準的な方法がなかった。Swift 6.2のObservations型がまさにそれを解決します。
@Observable
final class TemperatureSensor {
var temperature: Double = 20.0
var unit: String = "Celsius"
var isActive: Bool = true
}
let sensor = TemperatureSensor()
// Observationsで変更をストリーミング
let readings = Observations {
(sensor.temperature, sensor.unit)
}
// AsyncSequenceとして反復処理
for await (temp, unit) in readings {
print("現在の温度: \(temp) \(unit)")
updateDisplay(temperature: temp, unit: unit)
}
トランザクショナルな更新
Observationsの特に嬉しい点が、トランザクショナルな更新のサポートです。複数のプロパティが同期的に変更された場合、中間状態ではなく最終状態だけが通知されます。
@Observable
final class ShoppingCart {
var items: [Item] = []
var totalPrice: Double = 0.0
var itemCount: Int = 0
func addItem(_ item: Item) {
items.append(item)
totalPrice += item.price
itemCount += 1
// 3つのプロパティが変わっても、
// Observationsは1回だけ通知(最終状態で)
}
}
let cart = ShoppingCart()
let cartUpdates = Observations {
(cart.totalPrice, cart.itemCount)
}
for await (price, count) in cartUpdates {
// すべての変更が完了した後の一貫した状態を受け取る
print("合計: ¥\(price) (\(count)品)")
}
これでUIが中間的な不整合な状態を表示するリスクがなくなります。SwiftUIのwithAnimationブロックと似た感覚で、同期的な変更がひとまとめに処理されるわけですね。
InlineArray:固定サイズ配列の新時代(SE-0453)
InlineArrayは、コンパイル時にサイズが決まる固定長配列です。普通のArrayがヒープにメモリを確保するのに対して、InlineArrayはスタック上にメモリを確保します。パフォーマンスにシビアな場面では、この違いがかなり効いてきます。
基本的な使い方
// 型パラメータで宣言
var planets: InlineArray<4, String> = ["Mercury", "Venus", "Earth", "Mars"]
// 省略記法(of構文)
var rgbaPixel: [4 of UInt8] = [255, 128, 64, 255]
// 型推論も使える
var scores: InlineArray = [98.5, 87.3, 95.1]
// 要素のアクセスと変更
print(planets[0]) // "Mercury"
planets[2] = "Terra"
// repeatingイニシャライザ
var matrix: [9 of Double] = .init(repeating: 0.0)
Arrayとの違い
// Array:ヒープ割り当て、動的サイズ
var dynamicArray: [Int] = [1, 2, 3]
dynamicArray.append(4) // OK:サイズ変更可能
// InlineArray:スタック割り当て、固定サイズ
var fixedArray: InlineArray<3, Int> = [1, 2, 3]
// fixedArray.append(4) // コンパイルエラー!サイズ変更不可
// パフォーマンスの違い:
// Array → 参照カウント + ヒープ割り当てのオーバーヘッド
// InlineArray → オーバーヘッドなし、直接メモリアクセス
実践的なユースケース
// ゲーム開発:固定サイズのスプライトバッファ
struct GameScene {
var bricks: [40 of Sprite]
init(template: Sprite) {
bricks = .init(repeating: template)
}
mutating func updateBrick(at index: Int, with sprite: Sprite) {
guard index < 40 else { return }
bricks[index] = sprite
}
}
// 画像処理:RGBAピクセルの表現
struct Pixel {
var channels: [4 of UInt8]
var red: UInt8 { channels[0] }
var green: UInt8 { channels[1] }
var blue: UInt8 { channels[2] }
var alpha: UInt8 { channels[3] }
init(r: UInt8, g: UInt8, b: UInt8, a: UInt8 = 255) {
channels = [r, g, b, a]
}
}
// 暗号・ハッシュ:固定長のバイト列
struct SHA256Hash {
let bytes: [32 of UInt8]
}
InlineArrayが輝くのは、サイズがコンパイル時に決まっていて、ヒープ割り当てを避けたいパフォーマンスクリティカルな場面です。ゲーム開発、画像処理、ネットワークプロトコル、組み込みシステムなど、低レベルのパフォーマンスが求められるところで真価を発揮します。
Span:安全なメモリアクセスの新標準(SE-0447)
Spanは、連続したメモリ領域への安全で所有権のないアクセスを提供する型です。C++のstd::spanに近い存在で、UnsafeBufferPointerの安全な代替として設計されています。
// Arrayからのスパン作成
let numbers = [1, 2, 3, 4, 5]
let span = numbers.span
// スパンを使った高性能なアクセス
func sum(_ data: Span<Int>) -> Int {
var total = 0
for element in data {
total += element
}
return total
}
let result = sum(numbers.span) // ヒープコピーなしでアクセス
Spanの特徴
Spanの最大の特徴はNon-Escapable型であること。スパンは参照しているメモリの寿命を超えて存在できません。この制約はコンパイル時にチェックされるので、use-after-freeのようなメモリ安全性の問題を根本的に防げます。
// Spanはメモリを所有しない。借用するだけ
func processData(_ span: Span<UInt8>) {
// spanはこの関数のスコープ内でのみ有効
for byte in span {
process(byte)
}
}
// Array、InlineArray、UnsafeBufferPointerなど
// 連続メモリを持つ任意の型からSpanを作成可能
let array: [UInt8] = [0xFF, 0xD8, 0xFF, 0xE0]
processData(array.span)
let inlineArray: InlineArray<4, UInt8> = [0xFF, 0xD8, 0xFF, 0xE0]
processData(inlineArray.span)
パーサー、シリアライザ、画像処理、ネットワークプロトコルなど、パフォーマンスと安全性の両方が求められる場面で、UnsafeBufferPointerの代わりに使うべき型です。
言語機能の強化
weak let(SE-0481)
これ、地味に嬉しい変更です。今まで弱参照はweak varでしか宣言できませんでしたが、Swift 6.2でweak letが使えるようになりました。
final class Session: Sendable {
weak let owner: User? // 変更不可だが、破棄される可能性がある
let sessionId: String
init(owner: User?, sessionId: String) {
self.owner = owner
self.sessionId = sessionId
}
}
// weak letの最大の利点:Sendableに準拠できる!
// weak varだとSendableに準拠できなかった
// (別スレッドからの書き込みでデータ競合のリスクがあるため)
weak letは「値は変更しないけど、参照先が解放される可能性はある」という意図を正確に表現できます。Sendable準拠が必要なクラスで弱参照を持ちたいとき、これまでは回避策が必要でしたが、もうスッキリ書けます。
Raw Identifiers(SE-0451)
バッククォートで囲むことで、スペースや特殊文字を含む識別子が作れるようになりました。
// HTTPステータスコードをenum caseとして表現
enum HTTPStatus: Int {
case `200 OK` = 200
case `301 Moved Permanently` = 301
case `404 Not Found` = 404
case `500 Internal Server Error` = 500
}
let status = HTTPStatus.`404 Not Found`
// テスト関数を人間が読みやすい名前で定義
import Testing
@Test
func `ユーザー名が空の場合にバリデーションエラーになる`() {
let validator = UserValidator()
let result = validator.validate(username: "")
#expect(result == .invalid(.emptyUsername))
}
@Test
func `パスワードが8文字未満の場合にエラーになる`() {
let validator = UserValidator()
let result = validator.validate(password: "short")
#expect(result == .invalid(.passwordTooShort))
}
個人的にはSwift Testingとの組み合わせが最高だと思っています。テスト関数名を日本語で書けるので、テストレポートの可読性が劇的に上がります。チームで「何のテストが落ちたのか」を共有するとき、関数名が日本語だと一目瞭然ですよね。
オプショナルのデフォルト値付き文字列補間(SE-0477)
struct UserProfile {
var name: String
var nickname: String?
var age: Int?
var bio: String?
}
let user = UserProfile(name: "田中太郎", nickname: nil, age: 28, bio: nil)
// Swift 6.1まで:nil合体演算子が必要
print("ニックネーム: \(user.nickname ?? "未設定")")
// Swift 6.2:default引数で直接指定
print("ニックネーム: \(user.nickname, default: "未設定")")
print("年齢: \(user.age, default: "非公開")")
print("自己紹介: \(user.bio, default: "まだ書かれていません")")
小さな変更ですが、日常のコーディングで意外と効きます。??よりも意図が明確で読みやすいですね。
メソッド・イニシャライザのKeyPath(SE-0479)
struct User {
var name: String
func displayName() -> String {
return name.capitalized
}
}
let users = [User(name: "alice"), User(name: "bob"), User(name: "charlie")]
// メソッドをKeyPathとして使用
let displayNames = users.map(\.displayName())
// ["Alice", "Bob", "Charlie"]
// 戻り値の型がクロージャとして扱われるパターン
let nameFunctions = users.map(\.displayName)
// [() -> String, () -> String, () -> String]
enumerated()のCollection準拠(SE-0459)
let fruits = ["りんご", "みかん", "ぶどう", "バナナ"]
// Swift 6.2:enumerated()がCollectionに準拠
// ランダムアクセスやインデックス操作が可能に
// SwiftUIのListでの使用例
struct FruitListView: View {
let fruits = ["りんご", "みかん", "ぶどう", "バナナ"]
var body: some View {
List(fruits.enumerated(), id: \.offset) { index, fruit in
HStack {
Text("\(index + 1).")
.foregroundStyle(.secondary)
Text(fruit)
}
}
}
}
以前はenumerated()の戻り値がSequenceにしか準拠していなかったので、SwiftUIのListに直接渡せなかったりして不便でした。Collection準拠になったことで、こうした場面がスムーズになっています。
メモリ安全性の強化
厳格メモリ安全モード(SE-0458)
Swift 6.2では、@safeと@unsafe属性による厳格メモリ安全モードが導入されました。安全でないコードがどこにあるかを明示的にマークする仕組みです。
// 安全でない操作は@unsafeまたはunsafeブロックでマーク
func optimizedCopy(from source: UnsafePointer<UInt8>,
count: Int) {
unsafe {
let buffer = UnsafeBufferPointer(start: source, count: count)
for i in 0..<count {
process(buffer[i])
}
}
}
// 強制アンラップも明示が必要
let name: String? = getUserName()
unsafe print(name.unsafelyUnwrapped)
// @safe属性で安全性を保証
@safe
func calculateTotal(items: [Item]) -> Double {
items.reduce(0) { $0 + $1.price }
}
このモードを有効にすると、コードレビューやセキュリティ監査で「安全でない箇所はどこか?」がすぐにわかるようになります。
Swift Testingの進化
Exit Tests(ST-0008)
fatalError()やpreconditionの失敗でプロセスが終了するコード、今までテストが書けなくて困っていませんでしたか? Swift 6.2のExit Testsで解決です。
@Test
func 不正な引数でプロセスが失敗する() async throws {
await #expect(processExitsWith: .failure) {
let dice = Dice()
dice.roll(sides: 0) // precondition failureが発生
}
}
@Test
func 正常終了コードを検証する() async throws {
await #expect(processExitsWith: .success) {
gracefulShutdown()
}
}
テスト添付ファイル(ST-0009)
テストが失敗したとき、「何が起きたのか」をもっと詳しく知りたい場面ありますよね。添付ファイル機能を使えば、テスト失敗時のデータを記録できます。
@Test
func キャラクター生成テスト() throws {
let character = CharacterBuilder.build(level: 10)
// テスト失敗時にキャラクターデータを添付
Attachment.record(character, named: "生成されたキャラクター")
#expect(character.health > 0)
#expect(character.level == 10)
// スクリーンショットの添付
let screenshot = renderCharacter(character)
Attachment.record(screenshot, named: "キャラクター描画結果")
#expect(screenshot.size.width > 0)
}
ConditionTrait評価(ST-0010)
// テスト条件をテスト外で評価
let isCI = ConditionTrait.disabled(
if: ProcessInfo.processInfo.environment["CI"] != nil,
"CI環境ではスキップ"
)
@Test(.disabled(if: isInSmokeTestMode))
func 完全な統合テスト() async throws {
// ...
}
正規表現の強化:後方参照アサーション(SE-0448)
ようやく後方参照(Lookbehind)が使えるようになりました。正規表現をよく使う人には待望の機能ですね。
let pricePattern = /(?<=¥)\d{1,3}(,\d{3})*/
let text = "商品A: ¥1,200、商品B: ¥3,450、送料: ¥500"
for match in text.matches(of: pricePattern) {
print("価格: \(match.output)")
}
// 出力:
// 価格: 1,200
// 価格: 3,450
// 価格: 500
// URLからドメインを抽出する例
let urlPattern = /(?<=https?:\/\/)[^\/]+/
let url = "https://developer.apple.com/swift"
if let domain = url.firstMatch(of: urlPattern) {
print("ドメイン: \(domain.output)")
// ドメイン: developer.apple.com
}
デバッグ・診断の改善
Backtrace API(SE-0419)
ランタイムでバックトレースをキャプチャして解析できるAPIが追加されました。本番環境でのエラー追跡に使えます。
func debugCurrentState() {
if let backtrace = try? Backtrace.capture(),
let symbolicated = try? backtrace.symbolicated() {
for frame in symbolicated.frames.prefix(10) {
print(" \(frame)")
}
}
}
// エラーハンドリングでの活用
func riskyOperation() throws {
do {
try performDatabaseQuery()
} catch {
let backtrace = try? Backtrace.capture()
logger.error("""
データベースクエリ失敗
エラー: \(error)
バックトレース: \(backtrace?.symbolicated()?.frames ?? [])
""")
throw error
}
}
開発環境の改善
言語機能だけじゃなくて、開発環境もかなり良くなっています。ざっと紹介しますね。
- バックグラウンドインデックス:Xcode 26でデフォルト有効に。プロジェクトを開いた瞬間からコード補完やジャンプが高速に動きます
- VS CodeでのLLDBデバッグ:Swift拡張機能にLLDBが組み込まれ、Xcode以外でもフル機能のデバッグが可能に
- Swiftプロジェクトパネル:VS Codeに専用のプロジェクトナビゲーションパネルが追加
- DocCライブプレビュー:ドキュメントを書きながらリアルタイムでプレビュー確認
- コンパイラ診断の細かい制御:診断グループ単位で警告の有効・無効を設定可能
// Package.swiftでの診断制御
.target(
name: "MyLibrary",
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency"),
.defaultIsolation(MainActor.self)
]
)
移行ガイド:Swift 6.1からのアップデート
Swift 6.2への移行は段階的に進めるのがおすすめです。一気にやろうとすると大変なので、以下のステップで少しずつ進めましょう。
ステップ1:Xcode 26へのアップデート
まずXcode 26をインストールして既存プロジェクトを開きます。Swift 6.2は後方互換性があるので、既存のコードはそのままコンパイルできるはずです。
ステップ2:新しい並行処理デフォルトの有効化
// Package.swiftに段階的に設定を追加
.target(
name: "MyApp",
swiftSettings: [
.enableExperimentalFeature("NonisolatedNonsendingByDefault"),
]
)
ステップ3:defaultIsolationの設定(UIモジュール向け)
.target(
name: "MyApp",
swiftSettings: [
.defaultIsolation(MainActor.self),
.enableExperimentalFeature("NonisolatedNonsendingByDefault"),
]
)
ステップ4:@concurrentの追加
バックグラウンド実行が必要な関数に@concurrentを追加します。これまで暗黙的にバックグラウンドで動いていたnonisolated async関数がデフォルトで呼び出し元のアクターで実行されるようになるので、意図的にバックグラウンド処理にしたいものを明示的にマークしてください。
class DataProcessor {
@concurrent
nonisolated func processLargeFile(_ url: URL) async throws -> ProcessedData {
let data = try Data(contentsOf: url)
return try await heavyProcessing(data)
}
}
ステップ5:新機能の段階的導入
InlineArray、Span、weak letなどの新機能は既存コードに影響を与えないので、新しく書くコードから順次取り入れていくのがスムーズです。
まとめ:Swift 6.2が変える開発体験
Swift 6.2は、大きく分けて3つの柱でSwift開発を前進させます。
1. 並行処理がぐっと身近に。デフォルトMainActor分離、nonisolated(nonsending)デフォルト、@concurrent属性によって、並行処理は「全員が理解しなければならない複雑な概念」から「必要なときだけオプトインする機能」に変わりました。
2. パフォーマンスと安全性の両立。InlineArrayとSpanで、C言語レベルのパフォーマンスをSwiftの型安全性・メモリ安全性を保ったまま実現できます。
3. 日々の開発体験の向上。weak let、Raw Identifiers、デフォルト値付き文字列補間、Observations、進化したテストフレームワーク——こうした積み重ねが、毎日のコーディングを確実に快適にしてくれます。
Swift 6.2のテーマは「Approachable Concurrency(親しみやすい並行処理)」ですが、その恩恵は並行処理だけにとどまりません。あらゆるレベルの開発者が、より少ないボイラープレートで、より安全で、より速いコードを書けるようになる。それがSwift 6.2の本当の価値だと思います。Xcode 26をインストールして、ぜひ新しい機能を試してみてください。