開発者向け
SwiftUI の「Cannot find 'Map' in scope」を解決
SwiftUI の「Cannot find 'Map' in scope」の原因と直し方。Map や WebView に2つ目の import が必要な理由と、iPhone Duo での WebView の使い方を解説。
AppleDuo 編集部公開 15分で読めます
このページの内容
SwiftUI のビューに地図を追加すると、ファイルにはすでに import SwiftUI があるのに、Xcode が 「Cannot find 'Map' in scope」 で止まってしまう。型は存在し、綴りも正しく、デプロイメントターゲットにも問題はありません。同じことは PhotosPicker や、iOS 26 で SwiftUI に加わったネイティブの WebView でも起こります。解決策は import を1行追加するだけですが、その理由を知ると、同じ系統のエラーをまとめて理解できます。
このガイドでは、エラーが出る理由、クロスインポートオーバーレイとは何か、2つ目の import が必要なビュー、そして iOS 26 の WebView を WebPage と組み合わせて使う方法を解説します。内容は Apple のドキュメントと WWDC のセッション、Swift Forums の設計に関する議論、iOS デベロッパ @sarunw の投稿に基づいています。WebView と WebPage は iOS 26.0 の新機能で、リリース間で詳細が変わる可能性があります。
SwiftUI で「Cannot find 'Map' in scope」と表示されるのはなぜ?
Map が SwiftUI に含まれていないからです。@sarunw の言葉を借りれば、「Map はクロスインポートオーバーレイにあるので、SwiftUI と MapKit の両方が必要です。」次のファイルはビルドに失敗します。
import SwiftUI
struct ContentView: View {
var body: some View {
Map() // error: cannot find 'Map' in scope
}
}
1行追加すればビルドできます。
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
Map()
}
}
Apple の Map のドキュメントでは、Map は MapKit の下に分類され、SwiftUI のビューとして説明されています。シンボルの内部名を見ると、Map は _MapKit_SwiftUI というモジュールに属しており、これは MapKit でも SwiftUI でもありません。この3つ目のモジュールがオーバーレイです。
このエラーに気づきにくい理由が2つあります。コンパイラのメッセージは import が足りないことに触れていません。また、@sarunw がクロスインポートオーバーレイについての記事で指摘しているように、Xcode のオートコンプリートは読み込まれていないモジュールの型を候補に出せません。そのため、Map は補完候補にも表示されないのです。
Swift のクロスインポートオーバーレイとは?
クロスインポートオーバーレイとは、ソースファイルが特定の2つのモジュールを import したときに、コンパイラが自動的に import するモジュールのことです。Swift Forums の設計に関する議論では、オーバーレイは「ソースファイル内の import の組み合わせ」から選ばれると説明されています。オーバーレイは1つ目のフレームワーク(declaring module)を再エクスポートし、2つ目のフレームワーク(bystanding module)も必要とする API を追加します。
なぜ Map を SwiftUI か MapKit に直接入れないのでしょうか。Map は View なので SwiftUI が必要で、MapKit の型と連携するので MapKit も必要です。どちらかのフレームワークに入れると、一方を使うすべてのアプリがもう一方も取り込むことになります。オーバーレイなら、ファイルが両方を求めたときにだけ読み込まれます。
この仕組みは SDK の中で確認できます。@sarunw によると、オーバーレイを持つフレームワークは Modules ディレクトリに .swiftcrossimport フォルダを含み、相手のモジュールごとに小さなファイルが1つずつ入っています。
SDK=$(xcrun --sdk iphonesimulator --show-sdk-path)
cd "$SDK/System/Library/Frameworks/MapKit.framework/Modules"
ls MapKit.swiftcrossimport
cat MapKit.swiftcrossimport/SwiftUI.swiftoverlay
SwiftUI.swiftoverlay は短い YAML ファイルで、オーバーレイのモジュール名 _MapKit_SwiftUI を指定しています。@sarunw の数えでは、iOS 26 SDK には36のクロスインポートオーバーレイがあります。
日々の開発で重要な影響が1つあります。import はファイルごとだということです。アプリのエントリポイントで MapKit を import しても、SwiftUI しか import していない別のファイルで Map が使えるようにはなりません。そのビューを使うファイルごとに、両方の import が必要です。
2つ目の import が必要な SwiftUI のビューは?
@sarunw の目安はこうです。その型が依存する2つのフレームワークを見つけて、両方を import すること。よく使うものを、Apple のドキュメントにある利用可能バージョンとともにまとめます。
| SwiftUI の API | 追加で import | 利用可能 |
|---|---|---|
Map、Marker、Annotation | MapKit | iOS 14(Map)、地図コンテンツは iOS 17 |
PhotosPicker | PhotosUI | iOS 16 |
WebView | WebKit | iOS 26 |
VideoPlayer | AVKit | iOS 14 |
SubscriptionStoreView | StoreKit | iOS 17 |
SpriteView | SpriteKit | iOS 14 |
SignInWithAppleButton | AuthenticationServices | iOS 14 |
Apple のドキュメントでは、これらのシンボルはそれぞれ自身のフレームワークと SwiftUI の両方に属するものとして記録されています。@sarunw の記事にはさらに多くの組み合わせが挙げられています。StoreKit との ProductView、QuickLook との .quickLookPreview(_:)、SceneKit や RealityKit との SceneView と RealityView、Translation との .translationPresentation、SwiftData との .modelContainer などです。
ですから、SwiftUI らしい型で「Cannot find 'X' in scope」が出たら、綴りの間違いや利用可能バージョンの問題を疑う前に、2つ目の import が足りないかどうかを確認しましょう。Map の中に Marker や Annotation を書く MapKit のコンテンツビルダー API は、Apple のセッション「Meet MapKit for SwiftUI」とともに iOS 17 で登場しました。
iOS 26 で SwiftUI のネイティブの WebView を使うには?
iOS 26 より前は、SwiftUI で Web ページを表示するには WKWebView を UIViewRepresentable で包む必要がありました。@sarunw の言葉では、「SwiftUI に iOS 26 でようやくネイティブの WebView が加わりました。」Apple のセッション「What's new in SwiftUI」では、Safari と同じく WebKit を基盤とする「アプリで Web コンテンツを表示するための新しい SwiftUI ビュー」と紹介されています。
WebView もクロスインポートオーバーレイの型です。Apple の WebView のドキュメントでは WebKit と SwiftUI の下に記載され、サンプルは両方の import から始まっています。利用規約のページやヘルプ記事なら、URL のイニシャライザだけで十分です。
import SwiftUI
import WebKit
struct HelpView: View {
var body: some View {
NavigationStack {
WebView(url: URL(string: "https://www.swift.org"))
.navigationTitle("Help")
.webViewBackForwardNavigationGestures(.disabled)
}
}
}
init(url:) はオプショナルの URL を受け取り、ページ内のリンクはブラウザと同じように機能します。Apple によると、WebView は ScrollView のようにスクロールし、scrollBounceBehavior(_:axes:) を受け付けます。WebKit は webViewBackForwardNavigationGestures(_:)、webViewLinkPreviews(_:)、webViewTextSelection(_:)、webViewContentBackground(_:) などのモディファイアを追加します。Apple のセッション「Meet WebKit for SwiftUI」によると、既存の findNavigator(isPresented:) モディファイアでページ内検索も追加できます。
WebPage で読み込み、ナビゲーション、JavaScript を扱うには?
URL のイニシャライザでは、ページについて何も知ることができません。タイトル、進捗、JavaScript が必要なときの @sarunw の助言は、「WebView を WebPage と組み合わせる」ことです。Apple の WebPage のドキュメントでは、インタラクティブな Web コンテンツを制御・管理する Observable クラスと説明されています。@State で保持して WebView(_:) に渡します。
import SwiftUI
import WebKit
struct BrowserView: View {
@State private var page = WebPage()
var body: some View {
NavigationStack {
WebView(page)
.navigationTitle(page.title)
.safeAreaInset(edge: .top) {
if page.isLoading {
ProgressView(value: page.estimatedProgress)
}
}
.toolbar {
Button("Reload", systemImage: "arrow.clockwise") {
page.reload(fromOrigin: false)
}
}
}
.onAppear {
page.load(URLRequest(url: URL(string: "https://www.webkit.org")!))
}
}
}
WebPage は監視可能なので、デリゲートもコーディネーターもなしに、タイトルとプログレスバーが自動で更新されます。Apple のドキュメントによると、WebPage は同時に1つの WebView にしかバインドできません。最初に使うことになるメンバーは次のとおりです。
| WebPage のメンバー | 得られるもの |
|---|---|
title、url | ページのタイトルと現在の URL |
isLoading、estimatedProgress | 読み込み状態と 0 から 1 までの進捗 |
themeColor | ページの theme-color メタタグの色 |
backForwardList | 履歴。項目を指定して読み込める |
load(_:)、load(html:baseURL:) | ナビゲーション。イベントの非同期シーケンスを返す |
callJavaScript(_:arguments:in:contentWorld:) | JavaScript を実行して結果を受け取る |
load を呼び出すたびに、ナビゲーションイベントの非同期シーケンスが返されます。Apple のセッションによると、ナビゲーションは startedProvisionalNavigation で始まり、その後完了するか失敗します。ページの読み込み完了を待つ必要がある場合は for try await でシーケンスを反復し、ビューからは currentNavigationEvent を読み取ります。
JavaScript については、callJavaScript は async throws で、オプショナルの Any を返します。arguments 辞書のキーは、スクリプト内のローカル変数になります。
let heading = try await page.callJavaScript(
"return document.querySelector(selector)?.textContent",
arguments: ["selector": "h1"]
) as? String
ナビゲーションを許可またはブロックするには、型を WebPage.NavigationDeciding に準拠させ、WebPage(configuration:navigationDecider:) に渡します。Apple のセッションでは、URLSchemeHandler プロトコルによるカスタム URL スキームも扱っています。
iOS 26 より前のバージョンに対応するには?
WebView と WebPage には iOS 26 以降が必要です。デプロイメントターゲットがそれより低い場合は、@sarunw が勧めているように、WKWebView のラッパーを残して実行時に選びます。
struct ArticleView: View {
let url: URL
var body: some View {
if #available(iOS 26.0, *) {
WebView(url: url)
} else {
LegacyWebView(url: url)
}
}
}
struct LegacyWebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
WKWebView()
}
func updateUIView(_ webView: WKWebView, context: Context) {
webView.load(URLRequest(url: url))
}
}
このファイルにも import SwiftUI と import WebKit の両方が必要です。従来の経路は SwiftUI がビューを更新するたびに再読み込みするので、実際のアプリでは load を呼ぶ前に現在の URL と比較してください。デベロッパの Sarah Reichelt は、セッションのナビゲーション追跡のサンプルが iOS 26 の後のベータでコンパイルできなくなったことを報告しているので、サンプルは自分の Xcode のバージョンで確認しましょう。
iPhone Duo で地図や Web ビューに特別な対応は必要?
import はどの iPhone でも同じように機能しますが、iPhone Duo ではこれらのビューが置かれるスペースが変わります。
- 開くと広くなる。 内側ディスプレイは、iPhone Duo のサイズクラスのガイドで説明しているように、どちらの向きでも幅と高さが regular です。地図や Web ビューは、スタックにプッシュする代わりに、
NavigationSplitViewでリストの隣に置けます。 - ツールバーのボタンが移動する。 上の Reload ボタンのように、
.toolbarでWebViewやMapに付けたボタンは、iOS 27.1 SDK でビルドすると縦向きバーに移動します。iPhone Duo の縦向きツールバーのガイドで勧めているように、シンボルとタイトルを与えましょう。これらのボタンのグループ化については iOS 26 のツールバーのガイドで解説しています。 - 端から端までのコンテンツ。 Apple のサンプルでは
WebViewに.ignoresSafeArea()を適用しています。iPhone Duo では、縦向きバーは片側にだけインセットを追加します。セーフエリアのガイドで紹介している Apple のガイダンスでは、背景はバーの下まで広げてもよいものの、インタラクティブな要素は内側に留めるべきとされています。Web ページはリンクだらけなので、その端を無視する前に、コンテンツがバーにかからないことを確認してください。 - 折り目。 カスタムボタンなど、地図の上に重ねて描くコントロールは、折り目から離して配置しましょう。その位置を取得する方法は、折り目の予約領域のガイドで紹介しています。
まとめ
- 「Cannot find 'Map' in scope」は2つ目の import が足りないことを意味します。
import SwiftUIの隣にimport MapKitを追加しましょう。 Map、PhotosPicker、WebViewはクロスインポートオーバーレイにあります。これは_MapKit_SwiftUIのような隠れたモジュールで、1つのファイルが両方のフレームワークを import したときにだけ読み込まれます。- import はファイルごとなので、そのビューを使うすべてのファイルに両方が必要です。
- iOS 26 では WebKit にネイティブの
WebViewが加わりました。シンプルなページにはWebView(url:)を、タイトル、進捗、ナビゲーション、callJavaScriptが必要ならWebPageと組み合わせたWebView(page)を使います。 - 古いターゲット向けには、
if #available(iOS 26.0, *)の裏にWKWebViewのラッパーを残しておきましょう。 - iPhone Duo では、地図や Web ビューの上のツールバーのアイテムが縦向きバーに移動するので、アイコンを与え、インタラクティブなコンテンツはセーフエリアの内側に留めましょう。
次は、iOS 26 の SwiftUI ツールバーのガイドで地図や Web ビューの上のボタンを整え、iPhone Duo 対応チェックリストをひととおり実施してください。アプリが折りたたみで何をできるかは、Built for the fold でご覧いただけます。
よくある質問
SwiftUI で「Cannot find 'Map' in scope」と表示されるのはなぜ?
Map は SwiftUI 自体ではなく、MapKit と SwiftUI のクロスインポートオーバーレイで宣言されているからです。コンパイラがこのオーバーレイを読み込むのは同じファイルで両方のモジュールを import した場合だけなので、import SwiftUI と一緒に import MapKit を追加してください。
Swift のクロスインポートオーバーレイとは?
_MapKit_SwiftUI のような隠れたモジュールで、2つのフレームワークを同時に必要とする API を追加します。ソースファイルが両方のフレームワークを import するとコンパイラが自動的に import するので、どちらのフレームワークももう一方に依存する必要がありません。
別のファイルで MapKit を import するだけで足りますか?
足りません。import はソースファイルごとに適用され、オーバーレイは各ファイルの import の組み合わせから選ばれます。Map を使うすべてのファイルに、import SwiftUI と import MapKit の両方が必要です。
SwiftUI のネイティブの WebView はどの iOS バージョンで追加されましたか?
WebView とそのモデル型である WebPage は iOS 26.0 の新機能で、WebKit に含まれています。使うには SwiftUI と WebKit を import します。それより前のバージョンでは、WKWebView を包む UIViewRepresentable のラッパーを残しておきましょう。
SwiftUI の WebView で JavaScript を実行するには?
WebPage を作成して WebView に渡し、スクリプトを指定して try await page.callJavaScript を呼び出します。結果はオプショナルの Any 値なので、想定する Swift の型にキャストしてください。
出典
- WebView · Apple Developer Documentation
- WebPage · Apple Developer Documentation
- Map · Apple Developer Documentation
- PhotosPicker · Apple Developer Documentation
- Meet WebKit for SwiftUI (WWDC25) · Apple Developer
- What's new in SwiftUI (WWDC25) · Apple Developer
- Meet MapKit for SwiftUI (WWDC23) · Apple Developer
- Cross-import overlays · Swift Forums
- Why some Swift types only appear when you import two modules · Sarunw
- SwiftUI has a native WebView in iOS 26 · Sarunw
- SwiftUI WebView · TrozWare (Sarah Reichelt)
- Cannot find Map in scope even though you imported SwiftUI? · @sarunw on X
- Map, PhotosPicker and WebView live in cross-import overlays · @sarunw on X
- SwiftUI finally has a native WebView in iOS 26 · @sarunw on X
- Pair WebView with WebPage · @sarunw on X
折りたたみを、アプリの一部に。
AppleDuo は iPhone Duo を本当に活かしたアプリとゲームを紹介しています。App Store へのリンクを添えて送ってください。ほかの開発者の作品も見られます。