Skip to content
All articles

Cannot Find 'Map' in Scope in SwiftUI? Fix Map and WebView Imports

Fix "Cannot find 'Map' in scope" in SwiftUI: why Map, PhotosPicker and WebView need a second import, and how WebView and WebPage work on iPhone and iPhone Duo.

By AppleDuo EditorialPublished 7 min read

Also available in:DeutschEspañolFrançais日本語Türkçe

On this page
  1. Why does SwiftUI say "Cannot find 'Map' in scope"?
  2. What is a cross-import overlay in Swift?
  3. Which SwiftUI views need a second import?
  4. How do I use SwiftUI's native WebView in iOS 26?
  5. How do I track loading, navigation and JavaScript with WebPage?
  6. How do I support iOS versions before 26?
  7. Do maps and web views need anything special on iPhone Duo?
  8. Key takeaways

You add a map to a SwiftUI view, the file already has import SwiftUI, and Xcode stops with "Cannot find 'Map' in scope." The type exists, the spelling is right, and the deployment target is fine. The same thing happens with PhotosPicker and with the native WebView that SwiftUI gained in iOS 26. The fix is a single import, but the reason behind it explains a whole family of errors.

This guide covers why the error appears, what a cross-import overlay is, which views need a second import, and how to use the iOS 26 WebView with WebPage. It's based on Apple's documentation and WWDC sessions, the Swift Forums design notes, and posts by iOS developer @sarunw. WebView and WebPage are new in iOS 26.0, and details can change between releases.

Why does SwiftUI say "Cannot find 'Map' in scope"?

Because Map isn't part of SwiftUI. As @sarunw puts it, "Map lives in a cross-import overlay, so you need both SwiftUI and MapKit." This file fails to build:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Map() // error: cannot find 'Map' in scope
    }
}

Add one line and it builds:

import SwiftUI
import MapKit

struct ContentView: View {
    var body: some View {
        Map()
    }
}

Apple's documentation for Map files it under MapKit and describes it as a SwiftUI view. The symbol's internal name places it in a module called _MapKit_SwiftUI, which is neither MapKit nor SwiftUI. That third module is the overlay.

Two details make the error harder to spot. The compiler message doesn't mention a missing import, and, as @sarunw notes in his article on cross-import overlays, Xcode's autocomplete can't suggest a type from a module that isn't loaded. So Map doesn't show up in completions either.

What is a cross-import overlay in Swift?

A cross-import overlay is a module that the compiler imports automatically when a source file imports two specific modules. The Swift Forums design discussion describes overlays chosen from "the combination of imports in a source file." The overlay re-exports the first framework, called the declaring module, and adds API that also needs the second, called the bystanding module.

Why not put Map in SwiftUI or MapKit directly? Map is a View, so it needs SwiftUI, and it works with MapKit types, so it needs MapKit. Putting it in either framework would make every app that uses one pull in the other. The overlay only loads when a file has asked for both.

You can see the mechanism in the SDK. According to @sarunw, a framework that has overlays ships a .swiftcrossimport folder in its Modules directory, with one small file per partner module:

SDK=$(xcrun --sdk iphonesimulator --show-sdk-path)
cd "$SDK/System/Library/Frameworks/MapKit.framework/Modules"
ls MapKit.swiftcrossimport
cat MapKit.swiftcrossimport/SwiftUI.swiftoverlay

The SwiftUI.swiftoverlay file is a short YAML file that names the overlay module, _MapKit_SwiftUI. @sarunw counts 36 cross-import overlays in the iOS 26 SDK.

One consequence matters day to day: imports are per file. Importing MapKit in your app's entry point doesn't make Map available in a different file that only imports SwiftUI. Each file that uses the view needs both imports.

Which SwiftUI views need a second import?

The rule of thumb from @sarunw: find the two frameworks the type depends on, and import both. These are the common ones, with availability from Apple's documentation:

SwiftUI APIAlso importAvailable from
Map, Marker, AnnotationMapKitiOS 14 (Map); iOS 17 for map content
PhotosPickerPhotosUIiOS 16
WebViewWebKitiOS 26
VideoPlayerAVKitiOS 14
SubscriptionStoreViewStoreKitiOS 17
SpriteViewSpriteKitiOS 14
SignInWithAppleButtonAuthenticationServicesiOS 14

Apple's documentation records each of these symbols as belonging to both its framework and SwiftUI. @sarunw's article adds more pairs, including ProductView with StoreKit, .quickLookPreview(_:) with QuickLook, SceneView and RealityView with SceneKit and RealityKit, .translationPresentation with Translation, and .modelContainer with SwiftData.

So when you see "Cannot find 'X' in scope" for a SwiftUI-looking type, check for a missing second import before you suspect a typo or an availability problem. MapKit's content-builder API, with Marker and Annotation inside Map, arrived in iOS 17 with Apple's Meet MapKit for SwiftUI session.

How do I use SwiftUI's native WebView in iOS 26?

Before iOS 26, showing a web page in SwiftUI meant wrapping WKWebView in a UIViewRepresentable. As @sarunw puts it, "SwiftUI finally has a native WebView in iOS 26." Apple's What's new in SwiftUI session calls it "a new SwiftUI view for showing web content in your app," powered by WebKit like Safari.

WebView is a cross-import overlay type too. Apple's WebView documentation lists it under WebKit and SwiftUI, and its examples start with both imports. For a terms page or a help article, the URL initializer is all you need:

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:) takes an optional URL, and links inside the page work like a browser. Apple notes that a WebView scrolls like a ScrollView and accepts scrollBounceBehavior(_:axes:). WebKit adds modifiers such as webViewBackForwardNavigationGestures(_:), webViewLinkPreviews(_:), webViewTextSelection(_:) and webViewContentBackground(_:). The existing findNavigator(isPresented:) modifier adds find in page, per Apple's Meet WebKit for SwiftUI session.

How do I track loading, navigation and JavaScript with WebPage?

The URL initializer can't tell you anything about the page. When you need the title, progress or JavaScript, @sarunw's advice is to "pair WebView with WebPage." Apple's WebPage documentation describes it as an Observable class that controls and manages interactive web content. Hold it in @State and pass it to 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")!))
        }
    }
}

Because WebPage is observable, the title and progress bar update on their own, with no delegate or coordinator. Apple's documentation adds that a WebPage can be bound to only one WebView at a time. These are the members you'll reach for first:

WebPage memberWhat it gives you
title, urlThe page title and current URL
isLoading, estimatedProgressLoading state and progress from 0 to 1
themeColorThe color from the page's theme-color meta tag
backForwardListHistory, which you can load an item from
load(_:), load(html:baseURL:)Navigation, returning an async sequence of events
callJavaScript(_:arguments:in:contentWorld:)Run JavaScript and get a result

Each load call returns an async sequence of navigation events. Apple's session says a navigation starts with startedProvisionalNavigation, then finishes or fails. Iterate the sequence with for try await when you need to wait for a page to finish, or read currentNavigationEvent from a view.

For JavaScript, callJavaScript is async throws and returns an optional Any. Keys in the arguments dictionary become local variables in the script:

let heading = try await page.callJavaScript(
    "return document.querySelector(selector)?.textContent",
    arguments: ["selector": "h1"]
) as? String

To allow or block navigations, conform a type to WebPage.NavigationDeciding and pass it to WebPage(configuration:navigationDecider:). Apple's session also covers custom URL schemes through the URLSchemeHandler protocol.

How do I support iOS versions before 26?

WebView and WebPage require iOS 26 or later. If your deployment target is lower, keep a WKWebView wrapper and choose at runtime, as @sarunw suggests:

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))
    }
}

The file still needs both import SwiftUI and import WebKit. The legacy path reloads whenever SwiftUI updates the view, so in a real app compare the current URL before calling load. One developer, Sarah Reichelt, found that the session's navigation-tracking sample stopped compiling in later iOS 26 betas, so check examples against your Xcode version.

Do maps and web views need anything special on iPhone Duo?

The imports work the same on every iPhone, but iPhone Duo changes the space these views live in.

  • More room when open. The inner display reports regular width and regular height in both orientations, as our guide to iPhone Duo size classes explains. A map or web view can sit next to a list in a NavigationSplitView instead of being pushed onto a stack.
  • Toolbar buttons move. Buttons you attach to a WebView or Map with .toolbar, like the Reload button above, go to the vertical bar when you build with the iOS 27.1 SDK. Give them a symbol and a title, as our iPhone Duo vertical toolbar guide recommends. Our iOS 26 toolbar guide covers grouping these buttons.
  • Edge-to-edge content. Apple's sample applies .ignoresSafeArea() to a WebView. On iPhone Duo, the vertical bar adds an inset on one side only. Apple's guidance in our safe area guide is that backgrounds may extend under bars but interactive elements should stay inside. A web page is full of links, so check that its content stays clear of the bar before you ignore that edge.
  • The crease. Any overlay controls you draw over a map, like a custom button, belong clear of the fold. Our guide to reserved regions on the fold shows how to find it.

Key takeaways

  • "Cannot find 'Map' in scope" means a missing second import: add import MapKit next to import SwiftUI.
  • Map, PhotosPicker and WebView live in cross-import overlays, hidden modules like _MapKit_SwiftUI that load only when one file imports both frameworks.
  • Imports are per file, so every file that uses the view needs both.
  • iOS 26 adds a native WebView in WebKit. Use WebView(url:) for simple pages and WebView(page) with a WebPage for title, progress, navigation and callJavaScript.
  • Keep a WKWebView wrapper behind if #available(iOS 26.0, *) for older targets.
  • On iPhone Duo, toolbar items over maps and web views move to the vertical bar, so give them icons and keep interactive content inside the safe area.

Next, tidy the buttons above your map or web view with our guide to the SwiftUI toolbar in iOS 26, then work through the iPhone Duo preparation checklist. To see what apps can do with the fold, browse Built for the fold.

Frequently asked questions

Why does SwiftUI say cannot find Map in scope?

Map is declared in a cross-import overlay of MapKit and SwiftUI, not in SwiftUI itself. The compiler only loads that overlay when the same file imports both modules, so add import MapKit alongside import SwiftUI.

What is a cross-import overlay in Swift?

It's a hidden module, such as _MapKit_SwiftUI, that adds APIs which need two frameworks at once. The compiler imports it automatically when a source file imports both frameworks, so neither framework has to depend on the other.

Is importing MapKit in another file enough?

No. Imports apply per source file, and the overlay is chosen from the combination of imports in each file. Every file that uses Map needs both import SwiftUI and import MapKit.

Which iOS version added SwiftUI's native WebView?

WebView and its model type WebPage are new in iOS 26.0 and are part of WebKit. Import SwiftUI and WebKit to use them. On earlier versions, keep a UIViewRepresentable wrapper around WKWebView.

How do I run JavaScript in a SwiftUI WebView?

Create a WebPage, pass it to WebView, and call try await page.callJavaScript with your script. The result is an optional Any value, so cast it to the Swift type you expect.

Sources

  1. WebView · Apple Developer Documentation
  2. WebPage · Apple Developer Documentation
  3. Map · Apple Developer Documentation
  4. PhotosPicker · Apple Developer Documentation
  5. Meet WebKit for SwiftUI (WWDC25) · Apple Developer
  6. What's new in SwiftUI (WWDC25) · Apple Developer
  7. Meet MapKit for SwiftUI (WWDC23) · Apple Developer
  8. Cross-import overlays · Swift Forums
  9. Why some Swift types only appear when you import two modules · Sarunw
  10. SwiftUI has a native WebView in iOS 26 · Sarunw
  11. SwiftUI WebView · TrozWare (Sarah Reichelt)
  12. Cannot find Map in scope even though you imported SwiftUI? · @sarunw on X
  13. Map, PhotosPicker and WebView live in cross-import overlays · @sarunw on X
  14. SwiftUI finally has a native WebView in iOS 26 · @sarunw on X
  15. Pair WebView with WebPage · @sarunw on X

Make the fold part of your app.

We showcase apps and games that do something real with iPhone Duo. Send us yours with a link to it on the App Store, or see what other developers have built.

[email protected]