Xcodeで「Module dependency cycle: UIKit.swiftmodule → … → UIKit.swiftmodule」と表示される場合、明示的モジュールの依存関係スキャンが循環を検出しています。UIKit自体を修正するのではなく、エラーに表示された経路を読み、プロジェクトのFramework、Bridging Header、Module Map、公開ヘッダーの相互importを解消します。
エラーの意味
Module dependency cycle:
UIKit.swiftmodule
→ MyFramework.swiftmodule
→ SomeClangModule.pcm
→ UIKit.swiftmodule
Xcode 26ではSwift Explicit ModulesがSwiftターゲットの標準になりました。コンパイラはビルド前に依存モジュールを走査して個別に構築するため、従来は暗黙的importや偶然のビルド順で隠れていた循環が明確なエラーとして現れることがあります。
発生しやすい条件
- Framework AがFramework Bをimportし、BもAをimportしている
- Bridging HeaderがSwift生成ヘッダー(
ProductModuleName-Swift.h)をimportしている - Umbrella Headerや公開ヘッダーが不要なUIKit・自社Frameworkをimportしている
module.modulemapがPrivate Headerや別モジュールのUmbrella Headerまで含んでいる- C/Objective-Cの公開ヘッダー内に実装専用依存関係が露出している
- Xcode 26への更新後、Explicit Modulesで依存関係が厳密に検査された
推奨する解決手順
1. 循環経路を最後まで読む
Issue NavigatorまたはBuild Logで「Module dependency cycle」の全経路を展開します。先頭のUIKitではなく、同じモジュールへ戻る直前にある自社Framework、Clang Module、PCMを探します。
UIKit.swiftmoduleが経路の両端に表示されても、UIKitが原因とは限りません。循環へUIKitを再導入したプロジェクト側ヘッダーやModule Mapが重要です。
2. ターゲット依存関係を一方向にする
A→B→Aとなっている場合は、共通型やプロトコルを第三の小さなモジュールへ移します。
Before: FeatureA → FeatureB → FeatureA
After: FeatureA → SharedInterfaces ← FeatureB
Target Dependencies、Link Binary With Libraries、Swift Packageのtarget dependenciesも確認し、不要な逆向き依存を削除します。
3. Bridging Headerを確認する
Bridging Headerから自ターゲットの-Swift.hをimportしないでください。Objective-CからSwiftを使う場合はObjective-Cの実装ファイル側で生成ヘッダーをimportし、Bridging HeaderにはSwiftから必要なObjective-Cヘッダーだけを置きます。
// MyProject-Bridging-Header.h
// NG: #import "MyProject-Swift.h"
#import "LegacyAPI.h"
4. 公開ヘッダーとModule Mapを最小化する
- 公開ヘッダーで不要な
#importを削除し、可能なら前方宣言を使う - 実装だけで使うヘッダーはPublicからProject/Privateへ移す
- Umbrella Headerに別Frameworkの包括ヘッダーを無条件で入れない
- カスタムModule Mapの
umbrella、header、exclude headerを見直す
@class SomeViewController;
@protocol SomeService;
5. 修正後にクリーンな依存グラフで確認する
- Product > Clean Build Folderを実行する
- Swift Packageを再解決する
- DerivedDataを削除してClean Buildを行う
- CIでも同じXcode版でビルドする
一時的な代替策
Xcode 26のリリースノートでは、重大な問題がある場合にExplicit Modulesを一時的に無効化できると案内されています。
SWIFT_ENABLE_EXPLICIT_MODULES = NO
これは移行用の回避策です。依存関係の循環自体を直すものではなく、将来のXcodeで同じ問題が再発する可能性があります。まず問題ターゲットに限定し、恒久対応としてヘッダーとモジュール構造を修正してください。
確認方法
- Clean Buildでdependency cycleが出ない
- Explicit Modulesを有効に戻してビルドできる
- Simulator・実機・Archiveのすべてが成功する
- 別MacまたはCIの空キャッシュ環境でも成功する
注意点
モジュール名を変更したり、検索パスを追加したりして循環を隠すと、異なるモジュールが同じヘッダーを取り込む問題につながります。完全な経路を保存し、最初にプロジェクト側へ戻るimportを取り除くのが安全です。
2026年9月16日時点で、すべてのUIKit.swiftmodule循環に共通するXcode修正版はAppleから示されていません。Xcode 26のExplicit Modules標準化を前提に、個々の依存グラフを修正する必要があります。
まとめ
このエラーはUIKitの故障ではなく、モジュール依存関係が一周していることを示します。エラー経路から自社モジュールを特定し、双方向ターゲット依存、Bridging Header、公開ヘッダー、Module Mapを整理してください。Explicit Modulesの無効化は、恒久修正までの限定的な回避策として扱います。
