“Import from iPhone or iPad” doesn’t work when any view contains a SwiftUI Toggle

This is a public reposting of FB14893699, in case it’s helpful to anyone else or especially in case someone else has seen this too and knows how to work around it.

If any view in the [active] window contains a Toggle – even one that’s disabled or hidden – then Continuity Camera (re. ImportFromDevicesCommands and importableFromServices) doesn’t work; all the submenu items under “Import from iPhone or iPad” are disabled.

Screenshot of the File menu with the "Import from iPhone or iPad" submenu expanded, and all items therein are disabled.

I don’t know if this is truly specific to Toggle, that’s just the example case I happen to have isolated [first?].

What’s really weird is that once a Toggle has ever been displayed, even if you subsequently remove it from the view hierarchy entirely the “Import from iPhone or iPad” submenu items all remain disabled.

import SwiftUI

@main
struct Example: App {
    @State var breakImportFromiDevice = true
    @State var text = ""

    var body: some Scene {
        WindowGroup {
            VStack {
                TextField("Input", text: $text) // Doesn't break anything.

                if breakImportFromiDevice {
                    Toggle("Break import from iDevice", isOn: $breakImportFromiDevice)
                }
            }
            .importableFromServices(action: { (images: [NSImage]) -> Bool in
                print("Load image!")
                return true
            })
        }.commands {
            ImportFromDevicesCommands()
        }
    }
}

There are some circumstances in which this gets “unbroken” during interactions with other views and so forth, which is 100% reproducible in my real app but I have no idea what the reason is. The steps involved in my real app are kinda ridiculous (and not in any way remotely a viable workaround) and make absolutely no sense – it only “unbreaks” when a specific view is in a specific weird state (itself kind of the result of a bug, albeit a benign one). And that weird state is merely whether it’s displaying one image or another – which as far as SwiftUI is concerned is not even a difference in view state, since I’m just swapping NSImages under the cover.

I figured it must be something to do with view focus, but after much experimentation I believe I can conclusively rule that out. No matter which view has focus, or how focus is configured, or which views are even focusable at all, the problem persists. Likewise for window focus and key state. And, [accessability-]focusable views other than Toggle – e.g. TextField – don’t cause any issues.

Frankly it’s baffling, and a mite infuriating. I can’t even conceive of how SwiftUI can be so incredibly broken regarding such basic functionality, and the apparent interaction of GUI elements that have absolutely no business together.


Tangentially, a few things I’ve noticed about this Continuity Camera feature:

  • “Add Sketch” doesn’t do anything. Unlike the other options, which open the camera app on the target iDevice, it has no effect. 🤷‍♂️
  • Within the Finder, you can right-click empty whitespace within a folder, and the contextual menu has this “Import from iPhone or iPad” option at the bottom. That’s pretty handy – until now I’d been doing it the “hard” way by taking a photo on my iPhone and AirDropping it across to my Mac.

    I’d never noticed that feature prior to debugging this problem (I wanted to confirm that multiple other apps worked just fine; that it wasn’t an issue with Continuity Camera system-wide).
  • TextEdit has the same feature but tweaks the wording to “Insert…” rather than “Import…”, which I thought is both a nice touch and frustratingly not something you can do in your own apps (at least, not in SwiftUI). 😕

Leave a Comment