필사 모드: モダン Swift 2026 — Swift 6.1 / SwiftUI 6 / SwiftData / Vapor 4 / Hummingbird 2 / swift-testing / Android Swift 詳細ガイド
日本語プロローグ — Objective-C が去った跡地、11 年後の Swift
2014 年 WWDC で Chris Lattner が Swift を発表したとき、観客席の反応は拍手というよりため息に近かった、ということを覚えている。「Objective-C は 30 年の重荷だったが、検証された重荷だった。また新しい言語を学ばないといけないのか?」 — それが 2014 年 6 月の空気だった。11 年経った 2026 年 5 月、その問いはもう消えている。iOS・macOS・watchOS・visionOS・tvOS のコードはほぼ全部 Swift だ。Objective-C は SDK 内部 API の一部とヒストリカルなコードに残るだけで、新規プロジェクトは初日から Swift で始まる。そしていま Swift は Apple プラットフォームの外へ出ようとしている — Linux サーバー、Android、組込み、そして Windows にも。
この記事は 2026 年 5 月時点の Swift エコシステムを一枚の地図にする。言語(Swift 6.1・6.2 preview)、UI(SwiftUI 6・SwiftData)、サーバー(Vapor 4・Hummingbird 2)、ツール(Tuist・Mint・SwiftPM)、コード品質(swift-syntax・swift-format・SwiftLint・SwiftFormat)、テスト(swift-testing)、新領域(Android Swift WG・Embedded Swift・swift-foundation 再実装)、そして韓国・日本での実際の使い手(カカオ・ライン・メルカリ・クックパッド・サイバーエージェント・ピクシブ)まで。どのツールをいつ使うか、なぜ strict concurrency が大きな変化なのか、そして Swift は本当に Apple の外でも生きていけるのか。
1. 2026 年のモダン Swift — Swift 6 の strict concurrency 時代
一行で要約する。**2026 年の Swift の核心は「データ競合をコンパイル時に捕まえる」だ。** Swift 6.0(2024 年 9 月リリース)が strict concurrency を既定にし、Swift 6.1(2025 年)が「complete」モードを安定化させ、Swift 6.2 preview がさらに滑らかな actor 移行体験を約束する。C++・Rust・Go がそれぞれの方法で解いてきた並行性の安全問題を、Swift は actor モデル + Sendable プロトコル + isolated キーワード + region-based isolation で解いた。
2026 年時点での Swift の座標。
| 領域 | 状態(2026.05) | 代表的なツール |
| --- | --- | --- |
| 言語 | Swift 6.1 stable | swift.org / Xcode 16 |
| 言語(preview) | Xcode 17 beta で Swift 6.2 | swift.org |
| UI フレームワーク(Apple) | SwiftUI 6(iOS 18 / macOS 15) | Apple SDK |
| データ(Apple) | SwiftData GA | Apple SDK |
| サーバー(事実上の標準) | Vapor 4 | vapor.codes |
| サーバー(Apple SSWG 後援) | Hummingbird 2 | hummingbird.codes |
| パッケージ管理 | swift-package-manager | swift.org |
| プロジェクト生成 | Tuist 4 | tuist.io |
| CLI ツール導入 | Mint | github.com/yonaskolb/Mint |
| マクロ・AST | swift-syntax | github.com/swiftlang/swift-syntax |
| フォーマッタ(Apple 公式) | swift-format | github.com/swiftlang/swift-format |
| フォーマッタ(コミュニティ) | SwiftFormat | github.com/nicklockwood/SwiftFormat |
| リンタ | SwiftLint | github.com/realm/SwiftLint |
| テスト(新規) | swift-testing(Swift 6.0+) | swift.org |
| テスト(レガシー) | XCTest | Apple SDK |
| Android | Android Swift WG(2024.11) | swift.org/android-workgroup |
| 組込み | Embedded Swift | swift.org/embedded |
| 標準ライブラリ再実装 | swift-foundation | github.com/swiftlang/swift-foundation |
核心の洞察 3 つ。
第一に、**strict concurrency こそが Swift 6 のアイデンティティだ。** async/await が Swift 5.5 で入り、5.7 で actor モデルが安定化し、5.10 で strict concurrency が opt-in で入った。Swift 6.0 がこれを既定にしたことで、古いコードをコンパイルすると一気に数百・数千の警告が降ってくる。これが移行コストになる — が、一度通り抜ければ、データ競合をコンパイル時に保証する世界を手に入れる。Apple 自身が同じ道を歩いており、外では Airbnb・Lyft・Uber といった大型 iOS アプリが 1~2 年がかりの移行を進めている。
第二に、**Swift は徐々に Apple の外へ出ている。** Vapor が 2016 年からサーバー Swift を支えてきたが、2024 年 11 月に Android Swift Working Group が発足し、Apple 外のトラックが公式化した。Embedded Swift は 2024 年 WWDC キーノートに登場し、16KB バイナリで STM32 上で動くデモを見せた。swift-foundation は Objective-C ベースの NSFoundation を純粋 Swift で書き直すプロジェクトで、2024 年から本格稼働している。
第三に、**ツールエコシステムは分裂から統合へ向かっている。** swift-format(Apple 公式)と SwiftFormat(Nick Lockwood)が共存し、SwiftLint(Realm)がリンタの椅子を守るが、Apple が swift-syntax を標準化したことで全員が同じ AST を使う。CocoaPods → Carthage → SwiftPM の移行はほぼ終わり、新規プロジェクトは SwiftPM が既定だ。Tuist は SwiftPM と Xcode の間を埋めて、モノリポ・マルチターゲットで地位を固めた。
2. Swift 6.1 — complete モード + raw identifiers
Swift 6.1 は 2025 年春にリリースされた maintenance + feature リリースだ。中核的な変化は二つ。
**第一に、strict concurrency「complete」モードの安定化。** Swift 6.0 が strict concurrency を既定にしたが、「minimal・targeted・complete」の三段階のどこまで強くするかはプロジェクトが決める。6.1 では complete モード自体の false positive と diagnostic 品質が大きく改善された。特に Sendable 推論がより賢くなり、明示的な `@Sendable` 注釈なしに安全性が証明できるケースが増えた。
**第二に、raw identifiers。** バッククォートで囲んだ識別子に空白や特殊文字が使えるようになった。テスト関数名を自然文で書きたいときに決定的だ。
@Test func `ユーザーがログインするとトークンが発行される`() async throws {
let user = User(email: "test@example.com")
let token = try await login(user)
#expect(!token.isEmpty)
}
// 通常の関数でも使える
func `compute checksum for v2 protocol`(_ data: Data) -> UInt32 {
// ...
}
この機能は swift-testing と組み合わさり、日本語・韓国語のテスト名を自然に書ける。メルカリ・サイバーエージェントといった iOS チームでの採用可能性が高い理由だ。
Swift 6.1 のその他小さな変化。
- **`@MainActor` 推論の強化** — UIView/UIViewController のサブクラスは自動的に `@MainActor` として推論される。
- **`nonisolated(unsafe)` の明示化** — リスクを認識した上で隔離を切る escape hatch が明示形になった。
- **typed throws GA** — `func foo() throws(MyError)` 形式。Rust の `Result` に似た型安全なエラー伝播。
- **package manager の noncopyable types 対応** — `~Copyable` ジェネリクスが SPM パッケージインターフェースに正式公開。
// typed throws
enum NetworkError: Error {
case timeout
case unauthorized
}
func fetch(_ url: URL) async throws(NetworkError) -> Data {
// ...
}
// 呼び出し側は NetworkError だけを catch
do {
let data = try await fetch(url)
} catch .timeout {
// ...
} catch .unauthorized {
// ...
}
typed throws は Java の checked exception を思い出させるが — Swift の実装はもっと軽い。単なる generic だ。`throws` 自体が `throws(any Error)` の sugar としてモデル化されている。
3. Swift 6.2 preview — concurrency 改善
Swift 6.2 は 2026 年秋の GA を目標に preview 段階にある。Xcode 17 beta に含まれる。中核の方向性はひとつ — **strict concurrency をもっと「既定らしく」する。**
6.0/6.1 でいちばんよく出る不満は「単純なコードが突然データ競合警告を受ける」だった。6.2 はその摩擦点を削る。
**1) `@MainActor` の既定推論の拡張。** UI コード以外にも SwiftUI View・ViewModel パターン・Combine publisher が自動的に `@MainActor` として推論される。新規プロジェクトはほぼ `@MainActor` のコードしか書かなくなり、明示的に `nonisolated` や別の actor 隔離を表示したときだけ worker コンテキストに落ちる。
**2) Sendable 自動推論の強化。** struct・enum はすべての格納プロパティが Sendable なら自動で Sendable になる。すでに 6.1 で始まった変化だが、6.2 では cross-module 推論まで広がる。
**3) `async let`・TaskGroup の診断改善。** いちばんよく間違えるのは「値をキャプチャして task に渡したが、その値が Sendable でない場合」だ。6.2 はどの変数がどの task に escape するかをより精密に追い、fix-it も親切になる。
**4) `Span` / `RawSpan` 型。** Rust の `&[T]`・`&str` に近い借用ビュー型。ArraySlice より軽く、安全なゼロコピーデータアクセスを可能にする。
// Swift 6.2 preview
extension Array {
func sumFirstHalf() -> Element where Element: Numeric {
let half: Span<Element> = self.span.prefix(self.count / 2)
return half.reduce(0, +)
}
}
**5) C++ interop の安定化。** Swift ↔ C++ 双方向 interop が 6.2 でもう一段安定化する。依存グラフ・テンプレートインスタンス化・RAII マッピングが滑らかになる。これは単なるツール改善ではなく — Swift を「既存 C++ コードベースに段階的に導入できる言語」に育てる作業だ。
6.2 のスローガンは「strict concurrency を見えなく(invisible)する」だ。よく書かれたコードなら、利用者はほぼ隔離注釈を書かずに安全なコードを書けるはず、というのが目標だ。
4. SwiftUI 6(iOS 18) — Mesh gradient / scroll position / View Transition
SwiftUI 6 は iOS 18 / macOS 15 / visionOS 2 と一緒に 2024 年秋にリリースされ、2025 年を通して安定化パッチが入った。最も目立つ新機能 3 つ。
**1) Mesh gradient.** 2D メッシュ格子に色を配置し、その間を補間するグラデーション。linear/radial よりはるかに表現力が高く、Sketch・Figma でしか見られなかった滑らかな色遷移を SwiftUI で native に描ける。
struct MeshDemo: View {
var body: some View {
MeshGradient(
width: 3,
height: 3,
points: [
.init(0, 0), .init(0.5, 0), .init(1, 0),
.init(0, 0.5), .init(0.5, 0.5), .init(1, 0.5),
.init(0, 1), .init(0.5, 1), .init(1, 1),
],
colors: [
.red, .purple, .blue,
.orange, .white, .cyan,
.yellow, .green, .mint,
]
)
.ignoresSafeArea()
}
}
**2) Scroll position binding.** `ScrollView` のスクロール位置を `@State` で双方向バインディング。古い iOS の `contentOffset` のような命令的 API を使わずに、「特定セルへ移動」「いまどこにスクロールしているか」の追跡が宣言的にできる。
struct ScrollDemo: View {
@State private var scrollPosition = ScrollPosition(idType: Int.self)
var body: some View {
ScrollView {
LazyVStack {
ForEach(0..<100, id: \.self) { i in
Text("Row \(i)")
.id(i)
}
}
.scrollTargetLayout()
}
.scrollPosition($scrollPosition)
.safeAreaInset(edge: .top) {
Button("Top") { scrollPosition.scrollTo(id: 0) }
}
}
}
**3) View Transition.** いわゆる Hero animation — 画面間共有要素遷移が selector なしで美しく入った。`matchedTransitionSource` と `navigationTransition` を組み合わせれば NavigationStack の遷移でも自然に動く。
@Namespace var ns
NavigationLink(value: photo) {
Image(photo.thumb)
.matchedTransitionSource(id: photo.id, in: ns)
}
.navigationDestination(for: Photo.self) { photo in
PhotoDetail(photo: photo)
.navigationTransition(.zoom(sourceID: photo.id, in: ns))
}
**4) その他小ネタ。**
- `@Entry` マクロ — Environment キーを 1 行で定義。
- `TabView` のリライト — sidebar 適応、fluid customization。
- `Charts` 改善 — 3D chart、vector-based annotation。
- `Subview` API — 子ビューをインデックス参照する新方式。ForEach 以外の一般 view tree にも適用可能。
iOS 18.4 以降は Translation framework が SwiftUI と統合され、画面内テキストを device-local で翻訳する view modifier が入った。Apple Intelligence 依存なので全機種で動くわけではないが — 日本語・韓国語を扱うアプリには魅力的。
5. SwiftData — Core Data の後継
Core Data は 2005 年に macOS 10.4 Tiger とともに登場した Apple の ORM だ。安定しているが — Objective-C 時代の API なので NSManagedObject・NSFetchRequest といった古いパターンが満載だ。SwiftData は同じ椅子を狙う Swift-native の後継で、2023 年 iOS 17 で発表され、2024-2025 年に本格的に安定化した。2026 年 5 月時点では新規プロジェクトの既定は SwiftData だ。
SwiftData の核 — **`@Model` マクロでクラスを定義すると自動的に persistent class になる。**
@Model
final class Note {
var title: String
var body: String
var createdAt: Date
@Relationship(deleteRule: .cascade) var tags: [Tag]
init(title: String, body: String, tags: [Tag] = []) {
self.title = title
self.body = body
self.createdAt = .now
self.tags = tags
}
}
@Model
final class Tag {
@Attribute(.unique) var name: String
init(name: String) { self.name = name }
}
SwiftUI で使うときは `@Query` で読み、`modelContext.insert()` で書く。
struct NoteList: View {
@Query(sort: \Note.createdAt, order: .reverse) var notes: [Note]
@Environment(\.modelContext) var modelContext
var body: some View {
List(notes) { note in
VStack(alignment: .leading) {
Text(note.title).font(.headline)
Text(note.body).lineLimit(2)
}
}
.toolbar {
Button("Add") {
modelContext.insert(Note(title: "New", body: ""))
}
}
}
}
裏では今でも Core Data が動いている。SwiftData は Core Data 上の Swift-native レイヤに過ぎないため — Core Data ベースアプリの段階的移行が可能だ。iCloud 同期(CloudKit)もそのまま動く。
SwiftData の限界 — 2025 年までいちばんよく聞こえた不満は「performance」だった。大規模 dataset(10 万行以上)で `@Query` が main thread で評価されて UI を止めたり、undo manager が意図せずすべての変更を stack に積む問題があった。iOS 18.x のパッチを経てかなり改善したが — 大規模カタログアプリならいまでも Core Data 直叩きを検討する。
他の選択肢。
- **GRDB.swift** — SQLite 上の Swift-native ORM。Core Data 依存なしで軽い。
- **Realm** — MongoDB 買収後も安定しているが新規採用は減少傾向。
- **Supabase Swift SDK** — バックエンドまで一緒に持っていきたい場合。
- **Drizzle ORM(サーバー Swift 側)** — サーバーで Postgres を扱うとき。
iOS アプリで小さいデータ(10MB 未満、1 万行未満)なら SwiftData が既定の選択肢。その上に行くと GRDB を見る。
6. Vapor 4 — サーバー Swift の標準
サーバーサイド Swift の事実上の標準は **Vapor 4** だ。2016 年に初版がリリースされ、2020 年に Vapor 4 が async/await を取り込み、2026 年 5 月時点では 4.x メジャーの中で進化を続けている。
Vapor の魅力は — **Express/Koa・Fastify・NestJS に似た馴染みあるルーティング + Swift の型安全。**
struct TodoController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let todos = routes.grouped("todos")
todos.get(use: index)
todos.post(use: create)
todos.group(":todoID") { todo in
todo.get(use: show)
todo.delete(use: delete)
}
}
func index(req: Request) async throws -> [Todo] {
try await Todo.query(on: req.db).all()
}
func create(req: Request) async throws -> Todo {
let todo = try req.content.decode(Todo.self)
try await todo.save(on: req.db)
return todo
}
func show(req: Request) async throws -> Todo {
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
throw Abort(.notFound)
}
return todo
}
func delete(req: Request) async throws -> HTTPStatus {
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
throw Abort(.notFound)
}
try await todo.delete(on: req.db)
return .noContent
}
}
Vapor の構成要素。
- **routing** — async-first ハンドラ、parameter binding。
- **Fluent ORM** — Postgres・MySQL・SQLite・MongoDB ドライバ。
- **Leaf** — テンプレートエンジン(server-rendered HTML)。
- **JWT** — 認証/認可。
- **Queues** — バックグラウンドジョブ、Redis ベース。
- **WebSocketKit** — 双方向通信。
- **OpenAPIKit / openapi-generator-swift** — OpenAPI コード生成。
production 事例 — Vapor は Kodeco(旧 Ray Wenderlich)、Transeo、Emerge Tools といった場所で production を回しており、Apple も一部の internal tooling を Vapor で書いていると知られている。トラフィック規模は Node/Go ほどではないが — Swift をクライアントとサーバーの両方で使いたいチームには強力な選択肢だ。
7. Hummingbird 2(Apple 後援) — Swift Server Workgroup
**Hummingbird** は Adam Fowler が作った alternative サーバーフレームワークだ。1.x 時代には「軽量 Vapor」と呼ばれていたが — 2024 年に 2.0 が出ると、Apple の Swift Server Workgroup(SSWG)が後援する標準候補に位相が上がった。
Hummingbird 2 の魅力 3 つ。
**1) 依存が少ない。** Vapor が Fluent・Leaf・JWT などフルスタックをまとめて提供するのに対し、Hummingbird はルータ + middleware + HTTP 処理だけを担う。ORM・テンプレート・認証は別パッケージで組み立てる。Express vs NestJS の関係に近い。
**2) Swift Concurrency native。** 初日から async/await + structured concurrency 基盤で設計されている。SwiftNIO の上で動くが — NIO の EventLoopFuture を直接露出しない。
**3) AWS Lambda 親和性。** コールドスタートが速くバイナリサイズが小さい。swift-aws-lambda-runtime とよく合うため — Swift on Lambda のシナリオで Hummingbird がだんだん既定になりつつある。
let router = Router()
router.get("/") { _, _ in
"Hello, Hummingbird 2"
}
router.get("/users/:id") { req, ctx in
let id = try ctx.parameters.require("id", as: Int.self)
return User.fetch(id: id)
}
let app = Application(
router: router,
configuration: .init(address: .hostname("0.0.0.0", port: 8080))
)
try await app.runService()
Vapor vs Hummingbird 決定ガイド。
| 項目 | Vapor 4 | Hummingbird 2 |
| --- | --- | --- |
| ポジショニング | フルスタックフレームワーク | マイクロルータ |
| ORM | Fluent バンドル | GRDB・その他別 |
| async/await | 後方互換性の中で | native 設計 |
| Lambda | 可能だが重い | コールドスタート速い |
| 学習曲線 | 低(Express-like) | 低(さらに小さい) |
| コミュニティ | 大(古い) | 成長中 |
| Apple 後援 | 非公式 | SSWG 公式 |
大きいモノリスや server-rendered HTML アプリなら Vapor。マイクロサービス・Lambda・最小バイナリが必要なら Hummingbird。SSR なしの API-only ならどちらもよくこなす。
8. Tuist + Mint + swift-package-manager — ビルド / ツール
**SwiftPM(swift-package-manager)** は Apple 公式のパッケージマネージャだ。CocoaPods・Carthage の時代はほぼ終わり、2026 年の新規プロジェクトは SwiftPM が既定だ。`Package.swift` で依存を宣言し、Xcode・CLI の両方が理解する。
// swift-tools-version: 6.1
let package = Package(
name: "MyLib",
platforms: [.iOS(.v17), .macOS(.v14)],
products: [
.library(name: "MyLib", targets: ["MyLib"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"),
],
targets: [
.target(name: "MyLib", dependencies: [
.product(name: "Collections", package: "swift-collections"),
]),
.testTarget(name: "MyLibTests", dependencies: ["MyLib"]),
]
)
**限界** — SwiftPM は単純なライブラリパッケージには良いが、iOS アプリのように storyboard・xcassets・info.plist・scheme が複雑に絡んだプロジェクトでは足りない。そこで登場したのが Tuist だ。
**Tuist** は `Project.swift`(SwiftPM ではなく、Tuist 独自の DSL)で Xcode プロジェクトを生成する。大きなモノリポでモジュールを細かく分け、モジュール間の依存グラフをコードで表し、キャッシュ・差分ビルドまで支える。
// Project.swift
let project = Project(
name: "MyApp",
targets: [
.target(
name: "MyApp",
destinations: .iOS,
product: .app,
bundleId: "com.example.MyApp",
infoPlist: .extendingDefault(with: [
"CFBundleShortVersionString": "1.0.0",
]),
sources: ["Sources/**"],
resources: ["Resources/**"],
dependencies: [
.target(name: "Core"),
.target(name: "Network"),
]
),
.target(name: "Core", destinations: .iOS, product: .framework, bundleId: "com.example.Core", sources: ["Modules/Core/**"]),
.target(name: "Network", destinations: .iOS, product: .framework, bundleId: "com.example.Network", sources: ["Modules/Network/**"], dependencies: [.target(name: "Core")]),
]
)
Tuist はカカオ・ライン・メルカリのようにモジュール数 100 を超えるモノリポで地位を固めた。`tuist generate` で Xcode プロジェクトを作り、`tuist build` でキャッシュされた差分ビルドを回す。2024 年に Tuist Cloud(その後 Tuist 本体に統合)が登場し、ビルドキャッシュをチーム単位で共有する機能も入った。
**Mint** は Swift で書かれた CLI ツールを導入するツールだ。SwiftLint・SwiftFormat・swiftgen・xcodegen・Sourcery といったツールを Homebrew の代わりに Mint で入れれば — チーム全員が同じバージョンを使うように `Mintfile` で固定できる。
Mintfile 例
realm/SwiftLint@0.59.1
nicklockwood/SwiftFormat@0.55.0
yonaskolb/XcodeGen@2.42.0
インストール
mint bootstrap
実行
mint run swiftlint
大きいチームでは SwiftPM(ライブラリ)+ Tuist(プロジェクト生成)+ Mint(CLI ツール)の三つを一緒に使うのが標準の組み合わせになった。
9. swift-syntax / swift-format / SwiftLint / SwiftFormat
この 4 つのツールはすべて「Swift ソースコードを扱う」という点で同じ家族だ。
**swift-syntax** — Apple が作った公式 AST ライブラリ。swift コンパイラが使うのと同じ lexer/parser を露出する。マクロ(`@Macro`、Swift 5.9+)を書くときに必須。ResultBuilder・Codable のようなコンパイラ機能をユーザコードで拡張できる。
**swift-format** — Apple 公式フォーマッタ。Google の swift-format を Apple が引き取り、swiftlang/ 組織配下に移した。決まったスタイルガイド(主に Apple style)に従い、オプションは多くない。swift-syntax ベース。
**SwiftFormat** — Nick Lockwood が作ったコミュニティフォーマッタ。オプションが非常に多く — 100 以上の rule をオン/オフできる。古いコードベースを段階的に整理するときに有利。
**SwiftLint** — Realm が作ったリンタ。JonAS・Mac・iOS の標準コーディング規約を強制する。フォーマッタではない(一部自動修正もあるが主目的は検査)。200+ rule、custom rule の定義可能。
違いを一表で。
| ツール | 役割 | オプション | Apple 公式 | 自動修正 |
| --- | --- | --- | --- | --- |
| swift-syntax | AST ライブラリ | n/a | あり | n/a |
| swift-format | フォーマッタ | 少 | あり | あり |
| SwiftFormat | フォーマッタ | 多 | なし | あり |
| SwiftLint | リンタ | 多 | なし | 一部 |
実務の組み合わせガイド。
- **新規プロジェクト** — swift-format(Apple style に従う)+ SwiftLint(検査)。
- **レガシープロジェクト** — SwiftFormat(オプションで旧スタイル維持)+ SwiftLint。
- **マクロ/メタプログラミング** — swift-syntax 直接。
SwiftLint config 例。
disabled_rules:
- trailing_whitespace
opt_in_rules:
- empty_count
- missing_docs
included:
- Sources
excluded:
- Tests/Resources
- .build
line_length:
warning: 120
error: 200
identifier_name:
min_length: 2
excluded:
- id
- i
- x
- y
custom_rules:
no_print:
name: "No print()"
regex: "print\\("
message: "Use Logger instead of print()"
severity: error
CI では SwiftLint を `--strict` で回し、swift-format または SwiftFormat を `--lint` で回して PR で止めるのが標準だ。
10. swift-testing(Swift 6.0 新規) — XCTest を置き換え
XCTest は Objective-C 時代の遺産だ。`func test...` 命名、`XCTAssertEqual()` ヘルパ、インスタンスタイムのライフサイクル — すべて OOP-first の設計だ。**swift-testing** は Swift 6.0(2024 年 9 月)とともに正式リリースされた新しいテストフレームワークで、Swift のマクロシステムを積極的に活用する。
基本比較。
// XCTest(昔)
final class CalculatorTests: XCTestCase {
func testAddition() {
let result = Calculator.add(2, 3)
XCTAssertEqual(result, 5)
}
func testDivision() throws {
let result = try Calculator.divide(10, 2)
XCTAssertEqual(result, 5)
}
}
// swift-testing(Swift 6.0+)
@Test func addition() {
let result = Calculator.add(2, 3)
#expect(result == 5)
}
@Test func division() throws {
let result = try Calculator.divide(10, 2)
#expect(result == 5)
}
違いが一目でわかる。`XCTAssertEqual(a, b)` のようにヘルパごとに違う関数を覚える必要がなく、`#expect(...)` はマクロなので失敗時に式全体を自動で分解して見せてくれる — Rust の `assert!` や Catch2 の `REQUIRE` に近い発想だ。
パラメータ化テスト。
@Test(arguments: [(2, 3, 5), (10, -3, 7), (0, 0, 0)])
func addition(a: Int, b: Int, expected: Int) {
#expect(Calculator.add(a, b) == expected)
}
条件付き実行。
@Test(.enabled(if: ProcessInfo.processInfo.environment["CI"] == nil))
func localOnlyTest() {
// ローカルマシンだけで実行
}
非同期テストは `async` を足すだけ。
@Test func fetchesUser() async throws {
let user = try await api.fetchUser(id: 1)
#expect(user.name == "Alice")
}
XCTest との共存 — swift-testing は XCTest と同じバイナリの中で一緒に動く。`import Testing` と `import XCTest` を同じターゲットに混在できる。だから全体を一度に移行する必要はなく — 新しいテストだけ swift-testing で書き、古いテストはそのまま残せる。
XCTest は消えない。UI テスト(`XCUIApplication`)と性能テスト(`measure { }`)は今でも XCTest 領域だ。swift-testing は unit/integration テストを狙う。
11. Android Swift Working Group(2024.11) — Swift on Android
2024 年 11 月、swift.org に短いが決定的な記事が上がった — **「Android Swift Working Group が発足した」。** Apple、Google(Android 側)、そしてコミュニティが一緒に Android で Swift を一級市民にするという宣言だった。
背景。以前にも Swift on Android の試みはあった。Readdle のような会社は社内で Swift で Android アプリを書くことに成功し、scade.io といった商用ツールがあり、swift-corelibs-foundation が Android ターゲットを部分対応していた。しかしすべて非公式・実験的で、標準ライブラリの一部が欠けたり、NDK 統合が不完全だったり、App Store ではなく Play Store にアップする道で詰まったりしていた。
Android Swift WG の目標(2024.11 発足時に公開された内容)。
1. **公式 toolchain** — swift.org から Android ターゲットバイナリを正式配布。
2. **標準ライブラリ互換性** — Foundation・Network・Concurrency すべて Android で動く。
3. **JNI bridge** — Swift ↔ Kotlin/Java の相互呼び出し。
4. **Android 専用ライブラリ** — Activity・Intent といったコア Android API への Swift native バインディング。
5. **ビルド統合** — Gradle の中で Swift モジュールをビルドする標準。
2026 年 5 月時点での進捗 — WG 発足から 1 年半が過ぎ、実験的 toolchain は配布されており hello world レベルは安定して動く。Foundation・Concurrency はほぼ動く。本物の production アプリを書ける段階ではまだないが — 2027 年頃には Kotlin Multiplatform と競合できるオプションになる可能性がある。
期待値 — Swift on Android は「Android アプリを Swift だけで書こう」ではなく「iOS コードのビジネスロジックを Android で再利用しよう」というのがより現実的なシナリオだ。UI は SwiftUI(iOS)+ Compose(Android)で別々に書き、モデル・ネットワーク・ドメインロジックだけ Swift で共有する絵だ。
代替 — Kotlin Multiplatform がすでに同じことをやっており、JetBrains 後援でより成熟している。Compose Multiplatform が iOS まで対応し領域を広げている。Swift on Android が定着するには KMP より良い何かを提供しなければならない — それが何かは 2027 年頃に明らかになるだろう。
12. swift-foundation 再実装(オープンソース) + Embedded Swift
**swift-foundation** は Foundation フレームワーク(NSString・NSDate・URLSession・JSONSerialization など)を Objective-C 依存なしに純粋 Swift で書き直すプロジェクトだ。github.com/swiftlang/swift-foundation で開発される。
なぜ書き直すか。古い Foundation は二つのバージョンがあった。Apple Darwin では Objective-C ベースの NSFoundation を、Linux では swift-corelibs-foundation(C ベース)を使っていた。同じ API を約束するが挙動が微妙に違った — date formatting、URL parsing、JSON encoding すべて OS ごとに違い、バグが片方だけにあることがしばしばだった。
swift-foundation の約束 — **全 OS で同じコードが動き、同じ挙動をする。** Darwin も段階的に swift-foundation へ乗り換える。2024-2025 年に Calendar・Date・JSONEncoder・URL といった核タイプが移行され、2026 年には URLSession・FileManager が移行中だ。
影響 — Linux/Server Swift で最大。これまでは macOS で動いていたコードが Linux で突然壊れたが、swift-foundation 以降そういうことはほぼなくなる。Embedded Swift・Android Swift でも同じ Foundation を使えるのが大きな変化だ。
**Embedded Swift** は 2024 年 WWDC キーノートに登場した新モードだ。通常の Swift は ARC・動的 dispatch・例外処理・Foundation 依存が重く、組込みマイクロコントローラ(STM32、ESP32)に載せるのが難しかった。Embedded Swift は Swift 言語の一部機能を抜いて、そのような環境で動く小さなバイナリを作る。
抜けるもの。
- **標準ライブラリの一部** — Foundation ほぼ全部、Combine、Concurrency runtime の一部。
- **動的機能** — runtime metadata reflection(Mirror)、JSONDecoder のすべての動的デコード。
- **例外** — `throws` は使えるが、runtime exception unwinding なし。
残るもの。
- **言語基本** — struct・enum・class・generic・protocol。
- **所有権システム** — `~Copyable`、`~Escapable`。
- **Concurrency の一部** — async/await の lightweight 版(`embedded` モード)。
- **C interop** — そのまま動く。
用途 — マイクロコントローラファームウェア、IoT デバイス、一部 driver/kernel モジュール。Apple は SecureEnclave のような一部内部コンポーネントを Embedded Swift で書き直していると知られている。外では ESP32 ボードで Embedded Swift を動かすデモや Raspberry Pi Pico のサンプルが swift-embedded-examples にある。
// Embedded Swift 例 — Raspberry Pi Pico LED 点滅
@main struct App {
static func main() {
let led = GPIO(pin: 25, direction: .output)
while true {
led.high()
sleep(milliseconds: 500)
led.low()
sleep(milliseconds: 500)
}
}
}
Rust on embedded(embedded-hal・esp-rs)との競争が始まった。Rust は 5-6 年早くスタートしたが — Apple の重さが乗った Embedded Swift がどこまで行くか、興味深い時期だ。
13. Concurrency — actors / async / await / Sendable
Swift Concurrency は 5.5(2021)に始まり、5.7(actor)・5.9(macros)・6.0(strict)・6.1(complete)を経て段階的に完成した。核の概念 4 つ。
**1) async/await.** 非同期コードを同期のように書く。Promise/Future が明示的に露出されない。
func fetchUser(id: Int) async throws -> User {
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
// 呼び出し
let user = try await fetchUser(id: 1)
**2) actor.** 状態を持つオブジェクト。内部データへのアクセスがシリアライズされ、データ競合を防ぐ。
actor Counter {
private var count = 0
func increment() { count += 1 }
func value() -> Int { count }
}
let counter = Counter()
await counter.increment() // actor 外部からは await 必須
let v = await counter.value()
**3) Sendable.** 「複数スレッドで安全に共有できる型」というマーカ protocol。コンパイラがこの印を見て、actor 境界を越える値の受け渡しを検査する。
struct UserInfo: Sendable {
let id: Int
let name: String // String は自動的に Sendable
}
class MutableBox {
var value: Int = 0 // class に mutable property → Sendable 不可
}
// MutableBox は Sendable ではない → actor 境界越えで送るとコンパイルエラー
**4) Strict Concurrency.** Sendable 検査をどこまで強くするか決めるコンパイラモード。Swift 6.0 から「complete」が既定になり、6.1 で false positive が大きく減った。
Package.swift で有効にする方法
.target(
name: "MyLib",
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency"),
]
)
**`@MainActor`.** UI コードはすべて main スレッドで動くべきという約束をコンパイラが強制する。
@MainActor
class ViewModel: ObservableObject {
@Published var users: [User] = []
func load() async {
let result = try? await api.fetchUsers() // worker actor で動く
self.users = result ?? [] // main actor に hop
}
}
ここで `api.fetchUsers()` は `@MainActor` 以外の actor コンテキストで動き、結果を受けて `self.users` に書くときに自動で main スレッドに hop する。C++/Java では人が直接 `dispatch_async(main_queue, ^{...})` のようなものを書かないといけなかったが — Swift はコンパイラが自動で処理する。
**region-based isolation**(Swift 6.0+)。単一インスタンスが一つの task から別の task へ「送られる」ことを許す新しい方式。昔は `Sendable` でなければ actor 境界を越えられなかったが、region isolation は「この値がいま一箇所でしか使われていないことを証明できれば」越えさせてくれる。
func process() async {
let data = NonSendableData()
await someActor.use(data) // Swift 5.x ではエラー、Swift 6.x の region isolation で許可
// ただし、この時点以降に data を再利用するとコンパイルエラー
}
これが strict concurrency の false positive を減らす最大の改善だ。
14. Observation + Macros — iOS 17+ 新機能
**Observation フレームワーク** は iOS 17(2023)に入った新規の reactive システムだ。以前の `@Published`/Combine ベースの `ObservableObject` パターンをもっと軽く置き換える。
旧方式(Combine ObservableObject)。
class UserStore: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
}
struct UserList: View {
@StateObject var store = UserStore()
var body: some View {
if store.isLoading { ProgressView() }
else { List(store.users) { Text($0.name) } }
}
}
新方式(Observation)。
@Observable
class UserStore {
var users: [User] = []
var isLoading = false
}
struct UserList: View {
@State var store = UserStore()
var body: some View {
if store.isLoading { ProgressView() }
else { List(store.users) { Text($0.name) } }
}
}
違い。
- `@Published` 不要 — Observation がマクロで自動処理。
- `ObservableObject` の準拠不要。
- `@StateObject` → `@State` に単純化。
- **きめ細かい invalidation** — 昔はどの published property が変わっても view 全体が再描画されたが、Observation は実際に view が読み取った property だけを追跡してそこだけ invalidate する。性能の大幅改善。
裏では `@Observable` マクロがクラスの中に KeyPath ベースの tracking コードを自動生成する。swift-syntax の上に書かれたマクロで、ユーザが自分で拡張することもできる。
**Macros(Swift 5.9+)。** マクロはコンパイル時にコードを生成するメカニズムだ。C マクロと違って — テキスト置換ではなく AST 変換だ。swift-syntax が露出する AST を受け取り、新しい AST を返す関数。
マクロの 2 種類。
**1) Freestanding macro** — `#stringify` のように呼ぶ。
let (result, code) = #stringify(2 + 3)
// コンパイル後: (5, "2 + 3")
**2) Attached macro** — `@AddCompletionHandler` のように宣言に付ける。
@AddAsync
func fetch(completion: @escaping (Result<Data, Error>) -> Void) {
// ...
}
// マクロが以下を自動生成:
// func fetch() async throws -> Data { ... }
標準ライブラリ・SDK がマクロを積極活用する。
- `@Observable` — 上で見たもの。
- `@Model`(SwiftData) — persistent class を生成。
- `#expect`(swift-testing) — assertion マクロ。
- `@Entry`(SwiftUI 6) — Environment キー定義。
- `#Predicate`(SwiftData/Foundation) — type-safe query。
ユーザ定義マクロを書く例(簡略)。
public struct StringifyMacro: ExpressionMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) -> ExprSyntax {
guard let argument = node.argumentList.first?.expression else {
fatalError("compiler bug: the macro does not have any arguments")
}
return "(\(argument), \(literal: argument.description))"
}
}
マクロは別のターゲット(`.macro(...)`)に定義され、コンパイラプラグインとしてビルドされる。通常コードと分離されているのでコンパイル時の安定性を保証する。
マクロの限界 — コンパイル時間が伸びる(swift-syntax 依存が重い)。だからよく使われるマクロは事前コンパイル済みバイナリで提供される傾向にある。
15. 韓国 / 日本 — カカオ、ライン、メルカリ、クックパッド、ピクシブ
Swift は韓国・日本の iOS チームの既定言語だ。誰がどう使うか — 公開されたカンファレンス発表・ブログ・採用情報を総合する。
**韓国。**
- **カカオ** — iOS アプリ(カカオトーク・カカオバンク・カカオマップ・カカオウェブトゥーン)はほぼ全部 Swift。カカオトークはモジュールが 100 を優に超える大規模モノリポで、Tuist 導入事例としても知られる。RxSwift → Combine → Swift Concurrency への移行を段階的に進行中。社内カンファレンス「if(kakao)」で SwiftUI・SwiftData 導入後記を毎年発表。
- **ライン** — 日本本社発のラインアプリが Swift ベース。韓国の Line Plus も Swift 標準。swift-testing 導入を早く試したチームのひとつとして知られる。
- **トス(Toss)** — すべての iOS は Swift。Tuist + モジュール化 + Combine + 一部 SwiftUI 導入。デザインシステムとコンポーネントライブラリを SwiftPM パッケージとして社内配布。
- **クーパン** — iOS アプリ Swift。古い ObjC コードも一部残っている移行事例。
- **当根(Karrot)** — Swift + SwiftUI を積極導入。社内 RFC で SwiftData 導入検討を発表。
- **ネイバー** — ネイバーアプリ・ネイバー地図・ウェブトゥーン・V LIVE など iOS は Swift。社内ライブラリ群を SwiftPM パッケージに整理する作業が知られている。
**日本。**
- **メルカリ** — iOS アプリ Swift、マイクロサービスの一部は Vapor・Hummingbird で検討。社内で swift-testing 移行ガイドを公開。
- **クックパッド** — iOS アプリ Swift。iOSDC Japan で SwiftUI 導入事例を発表。
- **サイバーエージェント(ABEMA、AmebaTV)** — ABEMA iOS は Swift + SwiftUI。社内の多数の iOS アプリが Tuist 使用。サイバーエージェントの iOS エンジニア多数が swift.org・iOSDC に積極的に貢献。
- **ピクシブ** — iOS アプリ Swift。pixivFANBOX・pixivSketch・BOOTH など姉妹アプリも Swift。
- **DeNA** — 社内すべての iOS アプリが Swift。社内 Swift toolchain ミラーを運用。
- **Yahoo! JAPAN(LY Corporation)** — Yahoo!・Yahoo! ニュース・Yahoo! 乗換などが Swift。
共通パターン。
- **CocoaPods → SwiftPM** 移行はほぼ終わった。
- **Combine → Swift Concurrency** 移行中。新規コードは async/await first。
- **UIKit + SwiftUI ハイブリッド** — 新画面は SwiftUI、旧画面は UIKit。段階的移行。
- **Tuist 導入** — モジュール数が 50 を超えるチームはほぼ全部。
- **XCTest → swift-testing** — 2025-2026 年に移行開始。
韓国・日本どちらも iOS エンジニア採用で「Swift Concurrency 経験」「SwiftUI 実戦経験」「モジュール化/Tuist 経験」がだんだん必須キーワードになっている。
16. 誰が Swift を選ぶべきか — iOS / Apple エコシステム / サーバー / 組込み
ドメイン別おすすめ。
**iOS / macOS / visionOS / watchOS / tvOS アプリ。**
- ほぼ既定。Swift + SwiftUI または Swift + UIKit。新規プロジェクトは SwiftUI first。
- 巨大な古い ObjC コードベースがあれば段階的移行。Apple 自身も同じ道。
- Flutter・React Native・Kotlin Multiplatform が代替だが — 本当に native の体験と最新 OS API が必要なら Swift が既定。
**サーバー。**
- **Vapor** — フルスタック web アプリ、server-rendered HTML が必要、Express のような馴染みある体験が欲しい。
- **Hummingbird** — マイクロサービス、AWS Lambda、最小依存が欲しい。
- Swift は Go・Rust・Node ほどサーバーの標準ではない。**いつわざわざ Swift をサーバーに使うか** — iOS チームとモデル・ドメインロジックを共有したいとき。同じ会社が iOS とサーバーを両方 Swift で持っていけば、コード再利用と採用プールが合流する。
**Linux / コンテナ。**
- Vapor または Hummingbird でコンテナ化されたマイクロサービス可能。Distroless ベースイメージで 50-100MB 程度。
- Go・Rust よりバイナリサイズは大きいが — Swift も stripped binary なら使える大きさ。
**Android。**
- 2026 年時点では production 推奨ではない。Kotlin Multiplatform がより安定。
- iOS のビジネスロジックを Android で再利用するのが目標なら — Android Swift WG の進捗を眺めつつ 2027 年以降に再評価。
**組込み / IoT。**
- Embedded Swift は ESP32・STM32・Raspberry Pi Pico で実験的によく動く。
- production なら Rust(embedded-hal)または C がいまでも既定。
- Swift を使う価値のあるシナリオ — Apple アクセサリのファームウェア、AirTag 系のデバイス。その他はもう少し時間が必要。
**機械学習 / データ。**
- Python が既定。Swift は Core ML 上でモデルを呼ぶときだけ。
- Swift for TensorFlow は終了した。復活の可能性低い。
**スクリプティング / CLI。**
- swift-argument-parser で CLI をよく書ける。
- ただし起動時間が Python・Node より遅く、single-binary 配布は SwiftPM build 後の stripped binary で可能。
- macOS dev ツールには良い選択。cross-platform CLI なら Go・Rust が今でも優勢。
**だから Swift を選ぶべき決定的な理由たち。**
1. **iOS・macOS アプリを作る** — 疑いなく既定。
2. **Apple プラットフォームに深く入る** — visionOS・watchOS・tvOS は Swift のみが事実上可能。
3. **strict concurrency を真面目に使いたい** — Rust のような安全性を GC・ライフタイムの負担なしに得る。
4. **型安全な SwiftUI 宣言的 UI を愛する** — Compose より馴染みやすく、API が綺麗という評価がある。
5. **iOS チームがサーバーコードも書きたい** — Vapor/Hummingbird で社内標準化。
**Swift を選ばない方がよい理由。**
1. **Windows デスクトップが主軸だ** — Windows でも Swift は動くが一級市民ではない。
2. **cross-platform mobile しか書かない** — Flutter・React Native・Kotlin Multiplatform がより成熟。
3. **サーバードメインの標準が別言語だ** — チームがすでに Go・Node・Java に慣れているなら、わざわざ移る理由は少ない。
4. **機械学習/データ** — Python。
5. **システムプログラミングで最強の安全性が必要** — Rust。
2026 年の Swift は — Apple プラットフォームでは既定、サーバーでは自分の場所を作り、Android・組込みではまだ約束を守っている途中。次の 1-2 年が Apple の外での Swift の運命を決める時期だ。
参考 / References
- swift.org 公式 — https://www.swift.org/
- Swift 6 アナウンス — https://www.swift.org/blog/announcing-swift-6/
- Swift 6.1 release — https://www.swift.org/blog/swift-6.1-released/
- Android Swift Working Group — https://www.swift.org/blog/swift-on-android-workgroup/
- Embedded Swift — https://www.swift.org/blog/embedded-swift-examples/
- swift-foundation — https://github.com/swiftlang/swift-foundation
- swift-syntax — https://github.com/swiftlang/swift-syntax
- swift-format — https://github.com/swiftlang/swift-format
- swift-testing — https://github.com/swiftlang/swift-testing
- swift-package-manager — https://github.com/swiftlang/swift-package-manager
- SwiftLint — https://github.com/realm/SwiftLint
- SwiftFormat — https://github.com/nicklockwood/SwiftFormat
- Tuist — https://tuist.io/
- Mint — https://github.com/yonaskolb/Mint
- Vapor — https://vapor.codes/
- Hummingbird — https://hummingbird.codes/
- Swift Server Workgroup — https://www.swift.org/sswg/
- SwiftUI documentation — https://developer.apple.com/documentation/swiftui
- SwiftData documentation — https://developer.apple.com/documentation/swiftdata
- Observation framework — https://developer.apple.com/documentation/observation
- Macros proposal (SE-0382) — https://github.com/swiftlang/swift-evolution/blob/main/proposals/0382-expression-macros.md
- Strict Concurrency proposal (SE-0337) — https://github.com/swiftlang/swift-evolution/blob/main/proposals/0337-async-await-sendable-migration.md
- iOSDC Japan — https://iosdc.jp/
- if(kakao) カンファレンス — https://if.kakao.com/
- クックパッド開発者ブログ — https://techlife.cookpad.com/
- メルカリエンジニアリングブログ — https://engineering.mercari.com/
- pixiv 開発者ブログ — https://devpixiv.hatenablog.com/
현재 단락 (1/623)
2014 年 WWDC で Chris Lattner が Swift を発表したとき、観客席の反応は拍手というよりため息に近かった、ということを覚えている。「Objective-C は 30 年の重...