Supported read/write handoff of a sandbox-container PNG to Preview using NSWorkspace

Hello,

I am preparing an existing macOS screenshot utility for distribution through the Mac App Store.

The app stores captured PNG files under its temporary directory:

FileManager.default.temporaryDirectory .appendingPathComponent("ShelfDragPoC/Captures", isDirectory: true)

A context-menu "Edit" action passes the original PNG URL to Preview using NSWorkspace. The app does not create an editing copy.

Relevant code:

import AppKit

@MainActor func openInPreview(_ url: URL) { guard let previewURL = NSWorkspace.shared.urlForApplication( withBundleIdentifier: "com.apple.Preview" ) else { return }

let configuration = NSWorkspace.OpenConfiguration()
configuration.activates = true

NSWorkspace.shared.open(
    [url],
    withApplicationAt: previewURL,
    configuration: configuration
) { _, _ in }

}

The app monitors the original PNG URL for file changes and refreshes its thumbnail when changes are detected.

Observed behavior:

  1. In the existing non-sandboxed app, rotating an image in Preview updates the original PNG and the thumbnail without requiring Command-S.

  2. In the sandboxed validation app, Preview opens the image, but editing results in a separate copy.

  3. When closing the edited document, Preview displays a message indicating that the original document will not be changed.

  4. The original PNG and the app's thumbnail are not updated.

The Preview launch code and file watcher are unchanged between the non-sandboxed and sandboxed versions.

The sandboxed app has these entitlements:

  • com.apple.security.app-sandbox
  • com.apple.security.files.user-selected.read-write
  • com.apple.security.files.bookmarks.app-scope

The app-scoped bookmark is used for a separate Desktop export feature. The PNG opened in Preview remains in the app's sandbox container.

My question:

Is there a supported public API that allows a sandboxed Mac App Store app to open its own container-resident PNG in Preview with the permissions required for in-place editing and normal automatic saving?

Ideally, the user would only need to select "Edit" once, without an additional file-selection dialog or an explicit Save command.

We want to preserve the original PNG URL, keep App Sandbox enabled, and avoid automatically exporting temporary images to the Desktop.

If this workflow is not supported, what is Apple's recommended approach?

Thank you.

It's always risky trying to integrate with Apple's own apps.

Plus, in this modern age of paranoia, security restrictions may impact Apple apps as well as 3rd party apps. This file is in your app's container. I don't think what you're trying to accomplish is documented in any way. The only documentation and API support is to prevent the action you describe.

I think there are multiple other APIs to get data (or "document data") from one app to another. But then monitoring the other side is, at best, risky, and often flat-out impossible. The user can always rename or save elsewhere. If your app is claiming it can monitor that activity, the user is going to blame your app when it fails.

Then there's a more existential issue. You're essentially unhorsing yourself. You want users to use your app. The last thing you should ever do it launch someone else's app, even Apple's. It's your app. That's your user. Keep them in your app. Maybe you can use PDFKit and do those same operations totally inside your app.

This is going to be tricky. There are multiple potentially conflict file system permissions constraints in play here. I talk about those in On File System Permissions.

I’d like to clarify this bit of your question:

Written by SuzuyaKoboDev in 852014021

The app stores captured PNG files under its temporary directory:

Are you talking about the actual temporary directory, as returned by the temporaryDirectory property, or the older NSTemporaryDirectory()? Or a directory you manage that just happens to contain files that you consider temporary?

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn,

Thank you for looking into this.

It is A: FileManager.default.temporaryDirectory.

The app creates a subdirectory beneath the URL returned by that API:

FileManager.default.temporaryDirectory
    .appendingPathComponent("ShelfDragPoC/Captures", isDirectory: true)

The captured image is saved as a PNG using Data.write(to:options: .atomic), and the resulting URL is passed to Preview via NSWorkspace.open(_:withApplicationAt:configuration:completionHandler:).

The minimal reproduction project uses the same API and write method, with a different subdirectory (PreviewSandboxRepro/Captures) and a synthetic PNG.

Neither implementation explicitly calls NSTemporaryDirectory() or uses a separately chosen temporary-directory root.

Thank you!

Thanks for that extra info.

I’d like to tease apart sandbox restrictions from other restrictions associated with the temporary directory. If you put this PDF in a normal area of your app’s container, does that change the behaviour? For example, if you FileManager.default.temporaryDirectory to this:

let dir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

and thus put the PDF in your app’s Documents directory.

I’m not suggesting that this is an actual solution that you ship to customers; rather, it’s just a diagnostic test to see whether the temporary directory is part of this issue.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn,

I tested both locations with synthetic PNGs on macOS 26.6.2 (25G83), using Preview 11.0 (1113.5.3).

A used FileManager.default.temporaryDirectory.

B used FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).

I confirmed that B resolved to the app container's Documents directory, not the user's ordinary Documents folder.

Both cases used the same Apple Development-signed sandboxed app, identical initial PNG bytes, atomic writing, and the same NSWorkspace open call. The storage root, distinguishing A/B filename labels, and creation times differed.

For each PNG, I selected Rotate Left once in Preview without pressing Command-S, waited at least 10 seconds, and inspected the original file.

In both cases, Preview changed the document title to a copy. Both originals remained 640 × 360 pixels and 10,684 bytes, with unchanged SHA-256 and modification timestamps.

When closing B, Preview asked whether to keep the new copy and stated that the original document would not be changed. I cancelled without saving a separate copy.

The signed app has these three entitlements, all set to true:

  • com.apple.security.app-sandbox
  • com.apple.security.files.user-selected.read-write
  • com.apple.security.files.bookmarks.app-scope

Moving the PNG to the container's Documents directory did not change the observed behavior.

What would you recommend checking next?

Thank you!