今回はAIを利用して、WindowsやLinuxでSwiftUI風な記法で、WindowsやLinuxはたまたWebまで、うまく行けばSwiftでWrite once, run anywhere ほい事が実現できるのではないかと実験的なプロジェクトに取り組んでみました。なんとなくいい感じに仕上がってきたとおもうので、この場をかりて発表したいと思います。
背景
普段はiOSとMacのアプリのコードしか書かない私ですが、ある個人的なプロジェクトでLinuxとWindowのUIの実装をしたいなと思いました。Linuxは未経験、Windowsは3.1とかNTの頃で経験が止まっているので、AIと相談しながらコードを書いていました。Linux版など、どう進めればいいかもわからない感じでしたが、GimpやGTKなどをAIに教えてもらいながら、なんとか形になるぐらいの所まで仕上がってきました、
このくらいで欲がでてきます。「なんか、mac/iosのコード一回書いて使い回しができたらなんかよくね?」この後は頭のなかで理性のフューズが切れる音がします。SwiftWindowsUI、SwiftLinuxUIというリポジトリを作って、SwiftUI ぽいコードがうごくように、ViewやModifierを実装します。表面はSwiftでもその先はCへブリッジして、GTKやWin32のAPIに繋ぎます。
この二つが問題を抱えながらでもそれとなく動くようになってくるとふと思います。「おんなじ様なやり方でAndroidでもWebでもできるんでね?」ギアを上げる音がします。先ほど切れたと思ったフューズは高電力対応版に入れ替わっていました。やばい、フューズ飛びません。
二つのプロジェクト、SwiftWindowsUIとSwiftLinuxUIを一つにするにはどんな名前がある、そこでSwiftCrossUIというプロジェクトがある事に気がつきますが、もはや飛び出した慣性は制御できません。SwiftXUIとか考えましたが、いけていないと思い、AIにSwiftOpenUIという名前を考えてもらいました。「やばい、名前負けしそう」
司令塔はClaude Codeです。立案からコーディング、テストからメインでよく働いてくれます。司令塔とかいいながら、実際はよく使えるADくらいの感じです。本当によく働いてくれます。Claude Codeから大量に上がってくる計画やコードやドキュメントをレビューしてくれるのはCodexです。こいつは鬼レビューアです。ちょっと前までのChatGPTはゆるゆるだったのですが、執筆時点でのCodexはXcodeの名前の順番を入れ替えただけのパチモンと思いきや、実際にコードを確認したり、ドキュメントの記述が曖昧だったり、もうええやんと思う様な細かい重箱の隅をちゃんとしつこく指摘してくれます。自分がコード書いてたら、Codexにはあまりレビューしてもらいたくないです。
Geminiは助っ人役です。レビューをやらせると、褒めてしかくれません。Codexの爪の垢を飲ませたいです。おまけに、やるきマンマンで目がギラギラしているのか、レビューしてとお願いすると勝手にコードやドキュメントを修正しちゃう事があるので、「レビューして、レビューだけよ」と念をおさないと、時々やらかしてくれます。
まぁこんな環境で開発しています。環境ついでにいうと、Windows 11 が動くx86PCを持っていないので、開発は全て Mac Mini 2024, Apple M4 Pro, 64GB に UTMの仮想環境、そして、ARM版 Windows 11 Pro、ARM版 Ubuntu の仮想環境で、WindowsはWindows上のClaude、UbuntuはUbuntu上のClaudeとそれぞれでAgentを動かして作業しています。
動作環境
| プラットフォーム | バックエンド | 動作確認環境 |
|---|---|---|
| macOS | SwiftUI (ネイティブ) | macOS 15 Sequoia, Swift 6.2.4 |
| Linux | GTK4 | Ubuntu 24.04 (ARM64), Swift 6.0+ |
| Windows | Win32 + Direct2D | Windows 11 Pro (ARM64), Swift 6.0+ |
| Web | Wasm + DOM | Chrome / Safari, Swift 6.2.4 + Wasm SDK |
| Android | Jetpack Compose | 実験段階 (Phase 2) |
※ 開発は Mac Mini 2024 (M4 Pro, 64GB) 上で、Linux と Windows は UTM の仮想環境で動作確認しています。
スクリーンショット
同じSwiftコードが各プラットフォームでネイティブ描画されます。Electron やWebViewのラッパーではありません。
Color Studio — 1つのコードベース、4つのプラットフォーム
| macOS (SwiftUI) | Linux (GTK4) |
|---|---|
![]() |
![]() |
| Windows (Win32) | Web (Wasm) |
![]() |
![]() |
プロジェクト構造
コアライブラリ (Sources/SwiftOpenUI/) はプラットフォーム非依存で、プラットフォーム固有のimportは一切ありません。GTK/Win32/Web のコードは全て Sources/Backend/ に分離されています。
+-----------------------------------------------------+
| Examples (macOSではSwiftUI, それ以外はSwiftOpenUI) |
+-----------------------------------------------------+
| SwiftOpenUI Core |
| View, State, Layout, Modifiers, Environment |
+--------------+---------------+---------------+-------+
| BackendGTK4 | BackendWin32 | BackendWeb | ... |
| GTKRenderer | WinRenderer | WebRenderer | |
+--------------+---------------+---------------+-------+
| CGTK/Cairo | CWin32/D2D | JavaScriptKit| |
+--------------+---------------+---------------+-------+
各バックエンドはプロトコル拡張 (GTKRenderable, WinRenderable, WebRenderable) でレンダリングを実装します。新しいViewを追加するには、コアに構造体を定義して、各バックエンドにレンダリング拡張を書くだけです。
セットアップ
macOS
Xcode のコマンドラインツールがあれば動きます。
git clone https://github.com/codelynx/SwiftOpenUI.git
cd SwiftOpenUI
swift build
swift run HelloWorld
swift run ColorMixer
Xcode で開発する場合:
brew install xcodegen
cd apple/Examples && xcodegen generate
open Examples.xcodeproj
Linux (GTK4)
Swift ツールチェーンと GTK4 の開発ライブラリが必要です。
# Swift のインストール (swiftly 推奨)
curl -L https://swift.org/install.sh | bash
# GTK4 開発ライブラリ (Ubuntu / Debian)
sudo apt update
sudo apt install libgtk-4-dev pkg-config
# ビルド & 実行
git clone https://github.com/codelynx/SwiftOpenUI.git
cd SwiftOpenUI
swift build
swift run HelloWorld
swift run ColorMixer
Windows (Win32)
Swift for Windows と Visual Studio (Windows SDK) が必要です。
- swift.org/download から Windows 版 Swift をインストール
- Visual Studio 2022 で「C++ によるデスクトップ開発」ワークロードをインストール (Windows SDK を含む)
- Developer Command Prompt for VS 2022 を開いて:
git clone https://github.com/codelynx/SwiftOpenUI.git
cd SwiftOpenUI
swift build
swift run HelloWorld
swift run ColorMixer
Web (Wasm)
Xcode の Swift ではなく、オープンソース版の Swift ツールチェーンが必要です (Xcode版にはWasmバックエンドがないため)。
# 1. swiftly でオープンソース Swift をインストール
curl -L https://swift.org/install.sh | bash
source ~/.swiftly/env.sh
# 2. Wasm SDK をインストール
swift sdk install https://download.swift.org/swift-6.2.4-release/wasm-sdk/swift-6.2.4-RELEASE/swift-6.2.4-RELEASE_wasm.artifactbundle.tar.gz
# 3. Node.js (Vite 開発サーバー用)
brew install node # macOS の場合
# 4. ビルド & 実行
git clone https://github.com/codelynx/SwiftOpenUI.git
cd SwiftOpenUI
./web/run.sh HelloWorld
# ブラウザで http://localhost:3000 を開く
または、./configure スクリプトで swiftly + Wasm SDK を自動インストールできます (macOS のみ)。
Hello World
全プラットフォーム共通の main.swift です。Viewのコードは完全に同一で、#if で import とエントリーポイントだけを切り替えます。
#if os(macOS)
import SwiftUI
import AppKit
#else
import SwiftOpenUI
#if canImport(BackendGTK4)
import BackendGTK4
#endif
#if canImport(BackendWin32)
import BackendWin32
#endif
#if canImport(BackendWeb)
import BackendWeb
#endif
#endif
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack(spacing: 12) {
Text("Count: \(count)")
.font(.title)
Button("Increment") { count += 1 }
}
.padding()
}
}
struct MyApp: App {
var body: some Scene {
WindowGroup("My App") {
ContentView()
}
}
}
#if os(macOS)
NSApplication.shared.setActivationPolicy(.regular)
MyApp.main()
#elseif canImport(BackendGTK4)
GTK4Backend().run(MyApp.self)
#elseif canImport(BackendWin32)
Win32Backend().run(MyApp.self)
#elseif canImport(BackendWeb)
WebBackend().run(MyApp.self)
#endif
macOS では実際の SwiftUI としてコンパイルされるため、API の互換性が検証されます。他のプラットフォームでは SwiftOpenUI が同じプロトコル、プロパティラッパー、View 型を提供します。
実装状況
Views (43 / 44 実装済み)
Text, Button, TextField, Toggle, Slider, Image, Color, Spacer, Divider, VStack, HStack, ZStack, Group, ForEach, List, ScrollView, AnyView, EmptyView, NavigationStack, NavigationLink, SecureField, TextEditor, ProgressView, Stepper, Label, Link, TabView, Grid, GridRow, DisclosureGroup, Form, Section, LazyVStack, LazyHStack, LazyVGrid, LazyHGrid, Picker, DatePicker, GeometryReader, Menu, ConfirmationDialog, Canvas, NavigationSplitView
Modifiers (36 / 38 実装済み)
.padding(), .frame(), .foregroundColor(), .background(), .font(), .border(), .opacity(), .offset(), .scaleEffect(), .animation(), .onTapGesture(), .onLongPressGesture(), .onDrag(), .navigationTitle(), .navigationDestination(), .focused(), .cornerRadius(), .shadow(), .rotationEffect(), .overlay(), .sheet(), .alert(), .confirmationDialog(), .onAppear(), .searchable(), .toolbar() など
State 管理
@State, @Binding, @ObservedObject, @StateObject, @EnvironmentObject, @Published, @Environment, @FocusState, @Observable, ObservableObject
プラットフォーム別カバレッジ
| カテゴリ | SwiftUI 総数 | Core | GTK4 | Win32 | Web | カバレッジ |
|---|---|---|---|---|---|---|
| Views | 44 | 43 | 43 | 43 | 42 | ~98% |
| Modifiers | 38 | 36 | 36 | 36 | 36 | ~95% |
| State & Data | 13 | 10 | 10 | 10 | 10 | ~77% |
| Navigation | 8 | 7 | 7 | 7 | 7 | 88% |
詳細は Feature Parity Matrix を参照してください。
今後の課題
- Canvas の抽象化: GTK4 は Cairo、Win32 は Direct2D、Web は Canvas 2D API とそれぞれ異なる描画エンジンを使用。共通の DrawingContext API は動作しますが、プラットフォーム間の完全な互換性には更なる作業が必要です。
- Android: Phase 2 段階。JNI + Jetpack Compose でレンダリングしますが、共有コードのビルドに制約があります。
-
.onDisappear(): Web バックエンドのリビルドモデル (全DOM再構築) のため、正確なライフサイクル検出が困難です。 - パフォーマンス最適化: 現在はシンプルな全再構築モデル。差分更新やVirtual DOMは将来課題です。
ライセンス
MIT License
Copyright (c) 2026 Kaz Yoshikawa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software...
全文は LICENSE を参照してください。
リンク
- GitHub: https://github.com/codelynx/SwiftOpenUI
- Getting Started: docs/guides/getting-started.md
- Feature Parity Matrix: docs/architecture/swiftui-parity-matrix.md
- Web Parity Plan: docs/plans/web-parity-plan.md



