Modern versions of macOS use a file system permission model that’s far more complex than the traditional BSD rwx model, and this post is my attempt at explaining that model. If you have a question about this, post it here on DevForums. Put your thread in the App & System Services > Core OS topic area and tag it with Files and Storage.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
On File System Permissions
Modern versions of macOS have five different file system permission mechanisms:
Traditional BSD permissions
Access control lists (ACLs)
App Sandbox
Mandatory access control (MAC)
Endpoint Security (ES)
The first two were introduced a long time ago and rarely trip folks up. The second two are newer, more complex, and specific to macOS, and thus are the source of some confusion. Finally, Endpoint Security allows third-party developers to deny file system operations based on their own criteria. This post offers explanations and advice about all of these mechanisms.
Error Codes
App Sandbox and the mandatory access control system are both implemented using macOS’s sandboxing infrastructure. When a file system operation fails, check the error to see whether it was blocked by this sandboxing infrastructure. If an operation was blocked by BSD permissions or ACLs, it fails with EACCES (Permission denied, 13). If it was blocked by something else, it’ll fail with EPERM (Operation not permitted, 1).
If you’re using Foundation’s FileManager, these error are both reported as Foundation errors, for example, the NSFileReadNoPermissionError error. To recover the underlying error, get the NSUnderlyingErrorKey property from the info dictionary.
App Sandbox
File system access within the App Sandbox is controlled by two factors. The first is the entitlements on the main executable. There are three relevant groups of entitlements:
The com.apple.security.app-sandbox entitlement enables the App Sandbox. This denies access to all file system locations except those on a built-in allowlist (things like /System) or within the app’s containers.
The various “standard location” entitlements extend the sandbox to include their corresponding locations.
The various “file access temporary exceptions” entitlements extend the sandbox to include the items listed in the entitlement.
Collectively this is known as your static sandbox.
The second factor is dynamic sandbox extensions. The system issues these extensions to your sandbox based on user behaviour. For example, if the user selects a file in the open panel, the system issues a sandbox extension to your process so that it can access that file. The type of extension is determined by the main executable’s entitlements:
com.apple.security.files.user-selected.read-only results in an extension that grants read-only access.
com.apple.security.files.user-selected.read-write results in an extension that grants read/write access.
Note There’s currently no way to get a dynamic sandbox extension that grants executable access. For all the gory details, see this post.
These dynamic sandbox extensions are tied to your process; they go away when your process terminates. To maintain persistent access to an item, use a security-scoped bookmark. See Accessing files from the macOS App Sandbox. To pass access between processes, use an implicit security scoped bookmark, that is, a bookmark that was created without an explicit security scope (no .withSecurityScope flag) and without disabling the implicit security scope (no .withoutImplicitSecurityScope flag)).
If you have access to a directory — regardless of whether that’s via an entitlement or a dynamic sandbox extension — then, in general, you have access to all items in the hierarchy rooted at that directory. This does not overrule the MAC protection discussed below. For example, if the user grants you access to ~/Library, that does not give you access to ~/Library/Mail because the latter is protected by MAC.
Finally, the discussion above is focused on a new sandbox, the thing you get when you launch a sandboxed app from the Finder. If a sandboxed process starts a child process, that child process inherits its sandbox from its parent. For information on what happens in that case, see the Note box in Enabling App Sandbox Inheritance.
IMPORTANT The child process inherits its parent process’s sandbox regardless of whether it has the com.apple.security.inherit entitlement. That entitlement exists primarily to act as a marker for App Review. App Review requires that all main executables have the com.apple.security.app-sandbox entitlement, and that entitlements starts a new sandbox by default. Thus, any helper tool inside your app needs the com.apple.security.inherit entitlement to trigger inheritance. However, if you’re not shipping on the Mac App Store you can leave off both of these entitlement and the helper process will inherit its parent’s sandbox just fine. The same applies if you run a built-in executable, like /bin/sh, as a child process.
When the App Sandbox blocks something, it might generates a sandbox violation report. For information on how to view these reports, see Discovering and diagnosing App Sandbox violations.
To learn more about the App Sandbox, see the various links in App Sandbox Resources. For information about how to embed a helper tool in a sandboxed app, see Embedding a Command-Line Tool in a Sandboxed App.
Mandatory Access Control
Mandatory access control (MAC) has been a feature of macOS for many releases, but it’s become a lot more prominent since macOS 10.14. There are many flavours of MAC but the ones you’re most likely to encounter are:
Full Disk Access (macOS 10.14 and later)
Files and Folders (macOS 10.15 and later)
App bundle protection (macOS 13 and later)
App container protection (macOS 14 and later)
App group container protection (macOS 15 and later)
Data Vaults (see below) and other internal techniques used by various macOS subsystems
Mandatory access control, as the name suggests, is mandatory; it’s not an opt-in like the App Sandbox. Rather, all processes on the system, including those running as root, as subject to MAC.
Data Vaults are not a third-party developer opportunity. See this post if you’re curious.
In the Full Disk Access and Files and Folders cases, users grant a program a MAC privilege using System Settings > Privacy & Security. Some MAC privileges are per user (Files and Folders) and some are system wide (Full Disk Access). If you’re not sure, run this simple test:
On a Mac with two users, log in as user A and enable the MAC privilege for a program.
Now log in as user B. Does the program have the privilege?
If a process tries to access an item restricted by MAC, the system may prompt the user to grant it access there and then. For example, if an app tries to access the desktop, you’ll see an alert like this:
“AAA” would like to access files in your Desktop folder.
[Don’t Allow] [OK]
To customise this message, set Files and Folders properties in your Info.plist.
This system only displays this alert once. It remembers the user’s initial choice and returns the same result thereafter. This relies on your code having a stable code signing identity. If your code is unsigned, or signed ad hoc (Signed to Run Locally in Xcode parlance), the system can’t tell that version N+1 of your code is the same as version N, and thus you’ll encounter excessive prompts.
Note For information about how that works, see TN3127 Inside Code Signing: Requirements.
The Files and Folders prompts only show up if the process is running in a GUI login session. If not, the operation is allowed or denied based on existing information. If there’s no existing information, the operation is denied by default.
For more information about app and app group container protection, see the links in Trusted Execution Resources. For more information about app groups in general, see App Groups: macOS vs iOS: Working Towards Harmony
On managed systems the site admin can use the com.apple.TCC.configuration-profile-policy payload to assign MAC privileges.
For testing purposes you can reset parts of TCC using the tccutil command-line tool. For general information about that tool, see its man page. For a list of TCC service names, see the posts on this thread.
Note TCC stands for transparency, consent, and control. It’s the subsystem within macOS that manages most of the privileges visible in System Settings > Privacy & Security. TCC has no API surface, but you see its name in various places, including the above-mentioned configuration profile payload and command-line tool, and the name of its accompanying daemon, tccd.
While tccutil is an easy way to do basic TCC testing, the most reliable way to test TCC is in a VM, restoring to a fresh snapshot between each test. If you want to try this out, crib ideas from Testing a Notarised Product.
The MAC privilege mechanism is heavily dependent on the concept of responsible code. For example, if an app contains a helper tool and the helper tool triggers a MAC prompt, we want:
The app’s name and usage description to appear in the alert.
The user’s decision to be recorded for the whole app, not that specific helper tool.
That decision to show up in System Settings under the app’s name.
For this to work the system must be able to tell that the app is the responsible code for the helper tool. The system has various heuristics to determine this and it works reasonably well in most cases. However, it’s possible to break this link. I haven’t fully research this but my experience is that this most often breaks when the child process does something ‘odd’ to break the link, such as trying to daemonise itself.
If you’re building a launchd daemon or agent and you find that it’s not correctly attributed to your app, add the AssociatedBundleIdentifiers property to your launchd property list. See the launchd.plist man page for the details.
Scripting
MAC presents some serious challenges for scripting because scripts are run by interpreters and the system can’t distinguish file system operations done by the interpreter from those done by the script. For example, if you have a script that needs to manipulate files on your desktop, you wouldn’t want to give the interpreter that privilege because then any script could do that.
The easiest solution to this problem is to package your script as a standalone program that MAC can use for its tracking. This may be easy or hard depending on the specific scripting environment. For example, AppleScript makes it easy to export a script as a signed app, but that’s not true for shell scripts.
TCC and Main Executables
TCC expects its bundled clients — apps, app extensions, and so on — to use a native main executable. That is, it expects the CFBundleExecutable property to be the name of a Mach-O executable. If your product uses a script as its main executable, you’re likely to encounter TCC problems. To resolve these, switch to using a Mach-O executable. For an example of how you might do that, see this post.
Endpoint Security
Endpoint Security (ES) is a general mechanism for third-party products to enforce custom security policies on the Mac. An ES client asks ES to send it events when specific security-relevant operations occur. These events can be notifications or authorisations. In the case of authorisation events, the ES client must either allow or deny the operation.
As you might imagine, the set of security-relevant operations includes file system operations. For example, when you open a file using the open system call, ES delivers the ES_EVENT_TYPE_AUTH_OPEN event to any interested ES clients. If one of those ES client denies the operation, the open system call fails with EPERM.
For more information about ES, see the Endpoint Security framework documentation.
Revision History
2025-11-04 Added a discussion of Endpoint Security. Made numerous minor editorial changes.
2024-11-08 Added info about app group container protection. Clarified that Data Vaults are just one example of the techniques used internally by macOS. Made other editorial changes.
2023-06-13 Replaced two obsolete links with links to shiny new official documentation: Accessing files from the macOS App Sandbox and Discovering and diagnosing App Sandbox violations. Added a short discussion of app container protection and a link to WWDC 2023 Session 10053 What’s new in privacy.
2023-04-07 Added a link to my post about executable permissions. Fixed a broken link.
2023-02-10 In TCC and Main Executables, added a link to my native trampoline code. Introduced the concept of an implicit security scoped bookmark. Introduced AssociatedBundleIdentifiers. Made other minor editorial changes.
2022-04-26 Added an explanation of the TCC initialism. Added a link to Viewing Sandbox Violation Reports. Added the TCC and Main Executables section. Made significant editorial changes.
2022-01-10 Added a discussion of the file system hierarchy.
2021-04-26 First posted.
Files and Storage
RSS for tagAsk questions about file systems and block storage.
Posts under Files and Storage tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
General:
Forums subtopic: App & System Services > Core OS
Forums tags: Files and Storage, Foundation, FSKit, File Provider, Finder Sync, Disk Arbitration, APFS
Foundation > Files and Data Persistence documentation
Low-level file system APIs are documented in UNIX manual pages
File System Programming Guide archived documentation
About Apple File System documentation
Apple File System Guide archived documentation
File system changes introduced in iOS 17 forums post
On File System Permissions forums post
Extended Attributes and Zip Archives forums post
Unpacking Apple Archives forums post
Creating new file systems:
FSKit framework documentation
File Provider framework documentation
Finder Sync framework documentation
App Extension Programming Guide > App Extension Types > Finder Sync archived documentation
Managing storage:
Disk Arbitration framework documentation
Disk Arbitration Programming Guide archived documentation
Mass Storage Device Driver Programming Guide archived documentation
Device File Access Guide for Storage Devices archived documentation
BlockStorageDeviceDriverKit framework documentation
Volume format references:
Apple File System Reference
TN1150 HFS Plus Volume Format
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
My process running with root privilege, but got below error with API SecStaticCodeCreateWithPath(::_:) to create static code object for Cortex XDR Agent app, it working fine for other app like Safari on same device.
2025-07-22 02:02:05.857719(-0600)[23221:520725] DBG Found /Library/Application Support/PaloAltoNetworks/Traps/bin/Cortex XDR Agent.app,/Library/Application Support/PaloAltoNetworks/Traps/bin/Cortex XDR Agent.app running. Will verify the process now
2025-07-22 02:02:05.859209(-0600)[23221:520725] ERR Failed to create static code for path /Library/Application Support/PaloAltoNetworks/Traps/bin/Cortex XDR Agent.app/Contents/MacOS/Cortex XDR Agent. Error: Optional(UNIX[Operation not permitted])
Code Snippet
let fileURL = URL(fileURLWithPath: processPath)
var code: SecStaticCode?
let rc = SecStaticCodeCreateWithPath(fileURL as CFURL, [], &code)
if rc == errSecSuccess, let code = code {
staticCode = code
} else {
ZSLoggerError("Failed to create static code for path \(processPath). Error: \(String(describing: SecCopyErrorMessageString(rc, nil)))")
return nil
}
On macOS 26.1 (25B78) I can't give Full Disk Access to sshd-keygen-wrapper. Now my Jenkins jobs do not work because they do not have the permission to execute the necessary scripts. Until macOS 26.1 everything worked fine. I restarted the machine several times and tried to give access from Settings -> Privacy & Security -> Full Disk Access but it just does not work. I tried logging with ssh on the machine and executing a script but again nothing happened.
I’ve filed this as FB20943098 (macOS 26.1 – FileProvider v3 synchronous enumeration bug), but posting here in case others can reproduce and add duplicates.
Systems:
macOS 26.1 (26B82)
M4 Mac mini Pro and M4 MacBook Air
Symptoms:
In any app (TextEdit, Pages, Browsers, etc.), the Open/Save dialog lags for ~1s per folder navigation click. CPU spikes from fileproviderd, cloudd, bird, and siriactionsd.
Key discovery:
If my iCloud Drive root is empty (only “Documents” and “Downloads”), performance is perfect.
As soon as any folder or file exists at the root of iCloud Drive, the lag returns immediately.
Moving those items into “Documents” or “Downloads” makes everything smooth again.
Analysis:
Based on process traces and container paths, this appears to originate in the FileProvider.framework subsystem (via fileproviderd), which mediates iCloud Drive. Early evidence suggests that folder enumeration of the iCloud Drive container root may be blocking UI threads in macOS 26.1. I believe this may be related to the recent internal migration of the file-provider backend (often referred to as “v3”), but I do not have direct confirmation from Apple of that exact change.
MacOS 26.1’s new FileProvider v3 backend seems to be blocking the Open/Save panel while enumerating the iCloud Drive root container (~/Library/Application Support/FileProvider/723EBBFF-…).
Folder enumeration seems to wait synchronously for metadata from fileproviderd, and if the local SQLite DB is busy (WAL writes or sync state checks), UI freezes briefly.
Workarounds:
Disabling iCloud Drive entirely fixes the issue.
Simply disabling Desktop/Documents sync does not help.
Keeping the iCloud Drive root empty avoids the lag without turning iCloud off.
I am able to store whatever I please in the Desktop or Documents folder which is currently syncing.
Would appreciate if others on 26.1 could confirm.
Engineers: I’ve attached fs_usage, log stream, and process samples to my Feedback ticket via the FB20943098.
Expected behavior: Folder enumeration in NSOpenPanel should remain asynchronous regardless of FileProvider background activity. Open/save modal should be responsive and smooth.
I'm working on an iOS document-based app. It uses ReferenceFileDocument and custom creation of documents via DocumentGroupLaunchScene + NewDocumentButton. It works fine when I use the plain NewDocumentButton("Whatever") (without any more arguments), but when I want to perform additional setup via preapreDocumentURL or even just add a contentType it gives such output in the console when I hit it:
Content serialization failed, document won't be saved.
UTType.replayable is correctly wired up in the plist.
It looks like a bug in the SDK, but maybe there is a chance that I'm doing something wrong?
Here's a code:
import SwiftUI
import UniformTypeIdentifiers
import Combine
@main
struct MyApp: App {
var body: some Scene {
DocumentGroup {
Document()
} editor: { documentConfiguration in
EmptyView()
}
DocumentGroupLaunchScene("Yoyo") {
NewDocumentButton(contentType: .replayable) {
return URL(string: "whatever, it doesnt even go there...")!
}
}
}
}
final class Document: ReferenceFileDocument {
static var readableContentTypes: [UTType] { [.replayable] }
@Published var x = 0
init() {}
init(configuration: ReadConfiguration) throws {}
func snapshot(contentType: UTType) throws -> Data {
Data()
}
func fileWrapper(snapshot: Data, configuration: WriteConfiguration) throws -> FileWrapper {
.init(regularFileWithContents: snapshot)
}
}
extension UTType {
static var replayable: UTType {
UTType(exportedAs: "com.whatever.yo")
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags:
Files and Storage
File Provider
SwiftUI
Uniform Type Identifiers
Hey there,
I have an app that allows picking any folder via UIDocumentPickerViewController. Up until iOS18 users were able to pick folders from connected servers (servers connected in the Files app) as well.
On iOS26, the picker allows for browsing into the connected servers, but the Select button is greyed out and does nothing when tapped.
Is this a known issue? This breaks the whole premise of my file syncronization application.
When running the currently latest version of macOS (26.1) on a machine with ARM CPU (I could not reproduce the issue with Intel-Based machines) Finder Sync extensions do not work any more in general.
Steps to reproduce the problem:
In Xcode create a new macOS App project with default settings (in my case I chose XIB for the UI and Objective-C as language, and disabled testing, but that should not make any difference)
In Xcode add a new target / "Finder Sync Extension" to the project with default settings, this adds a new Finder Sync Extension with example code to the app.
Run the application and open Finder and navigate to "/Users/Shared/MySyncExtension Documents"
In the system settings ("Login Items & Extensions") enable the extension (Listed as "File Provider").
On systems where it is working, in the context menu of that folder an entry "Example Menu Item" will appear. On systems where it does not work it is missing.
Some findings:
Adding the *.appex with "pluginkit -a" registers the extension as expected, it is then visible in the system settings, removing it with "pluginkit -r" is also reflected in the system settings.
"pluginkit -m -i " returns the extension on systems where it is working (assuming it is registered while this command is executed), on systems wehre it is not working, nothing is returned, regardless of the registration state.
When enabling the extension in the system settings nothing more happens, there is no process started for the extension (unlike as on systems where it is working), and thus no context menu entries and no badges are displayed in Finder.
Restarting Finder or the system does not help.
Any ideas what I could be missing here?
I just saw another post regarding bookmarks on iOS where an Apple engineer made the following statement:
[quote='855165022, DTS Engineer, /thread/797469?answerId=855165022#855165022'] macOS is better at enforcing the "right" behavior, so code that works there will generally work on iOS. [/quote]
So I went back to my macOS code to double-check. Sure enough, the following statement:
let bookmark = try url.bookmarkData(options: .withSecurityScope)
fails 100% of the time.
I had seen earlier statements from other DTS Engineers recommending that any use of a URL be bracketed by start/stopAccessingSecurityScopedResource. And that makes a lot of sense. If "start" returns true, then call stop. But if start returns false, then it isn't needed, so don't call stop. No harm, no foul.
But what's confusing is this other, directly-related API where a security-scoped bookmark cannot be created under any circumstances because of the URL itself, some specific way the URL was initially created, and/or manipulated?
So, what I'm asking is if someone could elaborate on what would cause a failure to create a security-scoped bookmark? What kinds of URLs are valid for creation of security-scoped bookmarks? Are there operations on a URL that will then cause a failure to create a security-scoped bookmark? Is it allowed to pass the URL and/or bookmark back and forth between Objective-C and Swift?
I'm developing a new macOS app for release in the Mac App Store. I'm initially getting my URL from an NSOpenPanel. Then I store it in a SQLite database. I may access the URL again, after a restart, or after a year. I have a login item that also needs to read the database and access the URL.
I have additional complications as well, but they don't really matter. Before I get to any of that, I get a whole volume URL from an NSOpen panel in Swift, then, almost immediately, attempt to create a security-scoped bookmark. I cannot. I've tried many different combinations of options and flows of operation, but obviously not all.
I think this started happening with macOS 26, but that doesn't really matter. If this is new behaviour in macOS 26, then I must live with it.
My particular use requires a URL to a whole volume. Because of this, I don't actually seem to need a security-scoped bookmark at all. So I think I might simply get lucky for now.
But this still bothers me. I don't really like being lucky. I'd rather be right. I have other apps in development where this could be a bigger problem. It seems like I will need completely separate URL handling logic based on the type of URL the user selects.
And what of document-scoped URLs? This experience seems to strongly indicate that security-scoped URLs should only ever be document-scoped. I think in some of my debugging efforts I tried document-scoped URLs. They didn't fix the problem, but they seemed to make the entire process more straightforward and transparent. Can a single metadata-hosting file host multiple security-scoped bookmarks? Or should I have a separate one for each bookmark?
But the essence of my question is that this is supposed to be simple operation that, in certain cases, is a guaranteed failure. There are a mind-bogglingly large number of potential options and logic flows. Does there exist a set of options and logic flows for which the user can select a URL, any URL, with the explicit intent to persist it, and that my app can save, share with helper apps, and have it all work normally after restart?
A user of one of my apps reported that since the update to macOS 26.1 they are no longer able to scan Macintosh HD: the app used to work, but now always reports that Macintosh HD contains a single empty file named .nofollow, or rather the path is resolved to /.nofollow.
Initially I thought this could be related to resolving the file from the saved bookmark data, but even restarting the app and selecting Macintosh HD in an open panel (without resolving the bookmark data) produces the same result.
The user tried another app of mine with the same issue, but said that they were able to scan Macintosh HD in other App Store apps. I never heard of this issue before and my apps have been on the App Store for many years, but it looks like I might be doing something wrong, or the APIs that I use are somehow broken. In all my apps I currently use getattrlistbulk because I need attributes that are not available as URLResourceKey in all supported operating system versions.
What could be the issue? I'm on macOS 26.1 myself and never experienced it.
It's quite common for app bundles to be distributed in .zip files, and to be stored on-disk as filesystem-compressed files. However, having them both appears to be an edge case that's broken for at least two major releases! (FB19048357, FB19329524)
I'd expect a simple ditto -x -k appbundle.zip ~/Applications (-x: extract, -k: work on a zip file) to work. Instead it spits out countless errors and leaves 0 Byte files in the aftermath 😭
Please fix.
I need to detect the triggering of an auto-mount operation when accessing the path to a formerly unknown mount point at the file system (BSD, POSIX, NSURL) level, and how to wait for it to finish the operation.
Network shares can have sub-volumes on them
Consider a Windows server. Let's say there's a SMB sharepoint at C:\Shared. It has some folders, one of which is at C:\Shared\More. Furthermore, there's another partition (volume) on the PC, which is mounted at C:\Shared\More\OtherVol.
If you mount the initial share on a Mac with a recent macOS, macOS initially only sees a single mount point at /Volumes/Shared, which can be checked with the "mount" command.
Now, if you use Finder to dive into the Shared/More folder, Finder will trigger an auto-mount action on the containing OtherVol folder, and after that, the "mount" command will list two mount points from this server, the second being at /Volumes/Shared/More/OtherVol.
(This was a bit surprising to me - I'd have thought that Windows or SMB would hide the fact that the share has sub-volumes, and simply show them as directories - and that's what it did in older macOS versions indeed, e.g. in High Sierra. But in Sequoia, these sub-volumes on the Windows side are mirrored on the Mac side, and they behave accordingly)
Browse the volume, including its sub-volumes
Now, I have a program that tries to dive into all the folders of this Shared volume, even if it was just freshly mounted and there's no mountpoint at /Volumes/Shared/More/OtherVol known yet (i.e. the user didn't use Finder to explore it).
This means, that if my program, e.g. using a simple recursive directory scan, reaches /Volumes/Shared/More/OtherVol, the item will not appear as a volume but as an empty folder. E.g, if I get the NSURLIsVolumeKey value, it'll be false. Only once I try to enter the empty dir, listing its contents, which will return no items, an auto-mount action will get triggered, which will add the mountpoint at the path.
So, in order to browse the actual contents of the OtherVol directory, I'd have to detect this auto-mount operation somehow, wait for it to finish mounting, and then re-enter the same directory so that I now see the mounted content.
How do I do that? I.e. how do I tell that a dir is actually a auto-mount point and how do I wait for it to get auto-mounted before I continue to browse its contents?
Note that newer macOS versions do not use fstab any more, so that's of no help here.
Can the DA API help?
Do I need to use the old Disk Arbitration functions for this, somehow?
I have used the DA framework in the part to prevent auto-mounting, so I imagine I could hook into that handler, and if I get a callback for a mount operation, I could then queue the newly mounted volume for scanning. The problem, however, is that my scanning code may, having only seen an empty directory at the not-yet-mounted mountpoint, already decided that there's nothing there and finished its operation.
I'd need some reliable method that lets my recursive scanning code know whether an auto-mount has been triggered and it therefore needs to wait for the DA callback.
So, is there some signal that will let me know IMMEDIATELY after entering the empty mountpoint directory that an auto-mount op is on the way? Because I suspect that the DA callbacks come with a delay, and therefore would come too late if I used that as the notifier that I have to wait.
Hi, a short question really, which boils down to...
How do I make sure I have removed all usage of app groups in my Mac app store app, such that the Mac app store agrees I have!
Fundamentally, what I'm trying to do is transfer my app to another developer. In previous releases of this app on the App Store, I used a shared app group container to communicate between the main app and it's (embedded) XPC service, but this blocks App Store transfer of the app to another developer.
So I came up with another approach for the App and XPC service to communicate (using a URL bookmark for security scoped files to be passed to the XPC service). And then tried various things to get the app store to accept that I'm no longer using app groups. So far with no luck...
removed the app groups entitlements by hand from the entitlements files used to sign the main app and the XPC service, respectively.
when that didn't work, go into the Developer Portal, find the app ids for the main app and the XPC service, make sure those app ids had the app groups entitlement removed too, created a new provisioning profile for the app, based on this updated app id, downloaded it, rebuilt an app archive using this updated provisioning profile and used it to create another new release on the app store
when that didn't work, found and deleted all app app groups in my developer account in the developer portal itself
None of the above worked.
When I try to transfer the app in App Store Connect, I still see the same message, "You can't transfer this app because of the following reasons:
Sandboxed Group Container
You can only transfer sandboxed apps that are not sharing a group container."
I'm now pretty far from using a shared group container, so I'm puzzled why it still thinks I am?
There is one last thing I can try... I noticed over the weekend that even though the entitlement is gone, there's one place in code that may or may not be run on rare occasions (hard to tell) that attempts to open the app group shared container with the code...
let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:
...which I think is just returning nil and doing nothing. Potentially the App Store sees that attempted API access for shared group containers and assumes I'm still using app groups (even though there's no entitlement so that call will always be failing)?
I can do yet another App Store update and just remove that code.
But I want to get to the bottom of why it has been failing all this time. What is App Store Connect / the Mac App Store looking at that makes it think I'm still using app groups? I've tried so many things and don't want to mess users around with another App Store update unless this code above is the actual cause!
Cheers
p.s. It's a teamID based app group of the form... MY_TEAM_ID.s4a
e.g. SWDC5K54B7.s4a
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
Files and Storage
Entitlements
Code Signing
In the context of a FPUIActionExtensionViewController module the prepare method is defined like this:
override func prepare(forAction actionIdentifier: String,
itemIdentifiers: [NSFileProviderItemIdentifier]) {
So you would expect the itemIdentifiers list to be the item identifier but instead it is a list of the internal fileprovider IDs like: __fp/fs/docID(6595461)
So this is a bit problematic because the only way to recover the ID is by using getUserVisibleURL to get the path which is not great.
Is there a better way ?
Am I missing something ?
Thanks,
I am slowly converting an Objective C with C program to Swift with C. All of my menus and dialog boxes are now in Swift, but files are still opened and closed in Objective C and C. The following code is Objective C and tries to open two files in the same directory with two related names after getting the base of the name from a Save Panel. The code you see was modified by ChatGPT 5.0, and similar code was modified by Claude. Both LLMs wrote code that failed because neither knows how to navigate Apple’s sandbox. Does anybody understand Apple’s sandbox? I eventually want to open more related files and do not want the user to have to click through multiple file dialog boxes. What is the best solution? Are the LLMs just not up to the task and there is a simple solution to the Objective C code? Is this easier in Swift? Other ideas?
Thanks in advance for any help.
(BOOL)setupOutputFilesWithBaseName:(NSString*)baseName {
NSString *outFileNameStr = baseName;
if (outFileNameStr == nil || [outFileNameStr length] == 0) {
outFileNameStr = @"output";
}
// Show ONE save panel for the base filename
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setMessage:@"Choose base name and location for output files\n(Two files will be created: one ending with 'Pkout', one with 'Freqout')"];
[savePanel setNameFieldStringValue:outFileNameStr];
if (directoryURL != nil) {
[savePanel setDirectoryURL:directoryURL];
}
if ([savePanel runModal] != NSModalResponseOK) {
NSLog(@"User cancelled file selection");
return NO;
}
// Get the selected file URL - this gives us security access to the directory
NSURL *baseFileURL = [savePanel URL];
// Get the directory - THIS is what we need for security scope
NSURL *dirURL = [baseFileURL URLByDeletingLastPathComponent];
// Start accessing the DIRECTORY, not just the file
BOOL didStartAccessing = [dirURL startAccessingSecurityScopedResource];
if (!didStartAccessing) {
NSLog(@"Warning: Could not start security-scoped access to directory");
}
NSString *baseFileName = [[baseFileURL lastPathComponent] stringByDeletingPathExtension];
NSString *extension = [baseFileURL pathExtension];
// Create the two file names with suffixes
NSString *pkoutName = [baseFileName stringByAppendingString:@"Pkout"];
NSString *freqoutName = [baseFileName stringByAppendingString:@"Freqout"];
NSURL *pkoutURL = [dirURL URLByAppendingPathComponent:pkoutName];
NSURL *freqoutURL = [dirURL URLByAppendingPathComponent:freqoutName];
NSLog(@"Attempting to open: %@", [pkoutURL path]);
NSLog(@"Attempting to open: %@", [freqoutURL path]);
// Open the first file (Pkout)
globalFpout = fopen([[pkoutURL path] UTF8String], "w+");
if (globalFpout == NULL) {
int errnum = errno;
NSLog(@"Error: Could not open Pkout file at %@", [pkoutURL path]);
NSLog(@"Error code: %d - %s", errnum, strerror(errnum));
if (didStartAccessing) {
[dirURL stopAccessingSecurityScopedResource];
}
return NO;
}
NSLog(@":white_check_mark: Pkout file opened: %@", [pkoutURL path]);
// Open the second file (Freqout)
globalFpfrqout = fopen([[freqoutURL path] UTF8String], "w+");
if (globalFpfrqout == NULL) {
int errnum = errno;
NSLog(@"Error: Could not open Freqout file at %@", [freqoutURL path]);
NSLog(@"Error code: %d - %s", errnum, strerror(errnum));
fclose(globalFpout);
globalFpout = NULL;
if (didStartAccessing) {
[dirURL stopAccessingSecurityScopedResource];
}
return NO;
}
NSLog(@":white_check_mark: Freqout file opened: %@", [freqoutURL path]);
// Store the directory URL so we can stop accessing later
secureDirectoryURL = dirURL;
return YES;
}
Since macOS 26.1, creating bookmark data based on a NSOpenPanel URL, does not return the expected bookmark data when the selected source concerns a Windows NTFS fileshare.
When the returned data is being resolved, the returned URL points to the local drive of the current Mac. Which is of course super confusing for the user.
This issue did not occur in macOS 26.0 and older.
In essence, the following code line with 'url' based on an URL from a NSOpenPanel after selecting the root of a Windows NTFS share, creates an incorrect bookmark in macOS 26.1:
let bookmark = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
I have tested this on two different Macs with macOS 26.1 with two different Windows PC both hosting NTFS files shares via SMB.
My questions:
Have anyone else encountered this issue in macOS 26?
Perhaps even with other fileshare types?
Is there a workaround or some new project configuration needed in Xcode to get this working?
This script from man hdiutil no longer works:
devnode=$(hdiutil attach -nomount ram://102400)
newfs_hfs “$devnode”
mount -t hfs “$devnode” /path/to/ramdisk
because $devnode contains spaces and tabs!!
$ hdiutil attach -nomount ram://1 | xxd
00000000: 2f64 6576 2f64 6973 6b34 2020 2020 2020 /dev/disk4
00000010: 2020 2020 0920 2020 2020 2020 2020 2020 .
00000020: 2020 2020 2020 2020 2020 2020 2020 2020
00000030: 2020 2020 090a
# remember to clean up afterwards
$ hdiutil detach /dev/disk4
Please properly quote your variables in CI test scripts to catch such regression. It could pass because unquoted expansion of $devnode undergoes word splitting after the variable is substituted, removing the trailing whitespaces.
FB20303191
On iOS 18.0+ simulators, tap any share link button from any app, select "Save to Files", the "Save" button is disabled.
In all previous simulator versions this works. This behavior even happens with default Apple apps like Photos.
Simulator: Version 16.0 (1037)
XCode: Version 16.1 beta (16B5001e)
macOS: 14.6.1 (23G93)
When I drag and drop a file with flag "shouldAttemptToOpenInPlace: true", I was able to access the original file name in macOS 15.
After upgrading to macOS 26, I can't access the original file name anymore. Instead, I got some useless file name such as ".com.apple.Foundation.NSItemProvider.gKZ91u.tmp".
The app no longer works with these tmp filenames because it needs the orignal file name to do the file transfer. (Btw, this is a WinSCP like app on Mac platform)
Could you please check and fix this issue? Thank you.
FileRepresentation(contentType: .item, shouldAttemptToOpenInPlace: true)
I use the code below to rename a file, it works ok, but then the system calls accommodatePresentedItemDeletion(completionHandler:) on a NSFilePresenter that presents the file, immediately after the call to presentedItemDidMove(to:) What am I doing wrong?
NSFileCoordinator().coordinate(writingItemAt: oldURL, options: .forMoving, writingItemAt: newURL, options: [], error: &error)
{ (actualURL1, actualURL2) in
do {
coordinator.item(at: actualURL1, willMoveTo: actualURL2)
try FileManager().moveItem(at: actualURL1, to: actualURL2)
coordinator.item(at: actualURL1, didMoveTo: actualURL2)
} catch {...}
}
I'm downloading a fine-tuned model from HuggingFace which is then cached on my Mac when the app first starts. However, I wanted to test adding a progress bar to show the download progress. To test this I need to delete the cached model. From what I've seen online this is cached at
/Users/userName/.cache/huggingface/hub
However, if I delete the files from here, using Terminal, the app still seems to be able to access the model.
Is the model cached somewhere else?
On my iPhone it seems deleting the app also deletes the cached model (app data) so that is useful.