Guideline 2.4.5 is the list of extra requirements for apps sold on the Mac App Store. Two of its items have hit our Mac utilities: (i), "They must be appropriately sandboxed", and (vii), "They must use the Mac App Store to distribute updates; other update mechanisms are not allowed." Both pass every local build and test, because both are about where the app is distributed, not whether it works.
2.4.5(i): user files saved into the container
What Apple said. One of our Mac apps saved its output inside its own sandbox container. Apple's message: "The app saves user data to the app's container, which is not user accessible", quoting Apple's own sandbox guide: "the container is not for user documents." The suggested fix: "save user files to a location selected by or available to users, using standard Save dialogs."
Why it happens. In a sandboxed app, a plain write to the Documents directory works and the file exists, so nothing fails. It just lands in the app's container, a hidden location the user never opens. The container is meant for databases, caches and app data, not for things the user made.
How to fix it.
- AppKit: ask with
NSSavePanel. Apple's docs note that the panel runs in a separate process and that macOS adds the saved file to the app's sandbox, so you can write to the URL it returns.
let panel = NSSavePanel()
panel.nameFieldStringValue = "Notes.txt"
panel.allowedContentTypes = [.plainText]
if panel.runModal() == .OK, let url = panel.url {
try text.write(to: url, atomically: true, encoding: .utf8)
}
- SwiftUI: use the
fileExporter(isPresented:document:contentType:defaultFilename:onCompletion:)modifier with aFileDocument. - Entitlement: turn on App Sandbox in Xcode and set User Selected File to Read/Write (
com.apple.security.files.user-selected.read-write), so the app may write where the user picked.
Entitlements, the other half of (i). We have had two more 2.4.5(i) rejections over entitlements that were broader than the app needed. Before submitting, read the entitlements of the signed build, make sure get-task-allow is not there (an easy one to miss), and remove any entitlement you cannot explain in one sentence.
2.4.5(vii): a built-in update check
What Apple said. A Mac utility of ours had a "check for updates" feature. Apple: "The app contains frameworks or APIs that may be used to update the app outside of the Mac App Store", and "You should not provide additional update checks or updates through the app." The reviewer attached a screenshot of where it appeared.
Why it happens. The same code base often ships two ways: a direct download that needs its own updater, and the Mac App Store, which already tells users about updates. The updater comes along into the store build by default.
How to fix it. Note the wording: Apple names frameworks and APIs, not only the menu item. Hiding the button is not enough.
- Give the direct-download build its own configuration or target with a Swift compilation condition (Xcode's Active Compilation Conditions), for example
DIRECT_DOWNLOAD. - Wrap the updater code and its menu item in
#if DIRECT_DOWNLOAD ... #endif. - Link the update framework only into the direct-download target, so the Mac App Store binary does not contain it.
- Remove "check for updates" settings, preferences and onboarding text from the store build too.
One-minute check
On the archive you are about to upload: save something from the app and confirm a Save dialog asked you where. Open the app menu and Settings and confirm there is no update item. List the bundle's Contents/Frameworks folder and confirm no updater framework is inside. Then print the signed entitlements with codesign -d --entitlements - YourApp.app and read every line.
Mac apps also get a design rejection that iPhone apps never see: no way to reopen the main window. More release checks are on the toolkit page, and the commonest first rejection is 2.1, App Completeness.
These notes are from Obelisk Club's own submissions. Apple's wording and tools change; check the current App Review Guidelines and Apple's documentation for exact behaviour.