General:
DevForums tags: Files and Storage, Finder Sync, File Provider, Disk Arbitration, APFS
File System Programming Guide
On File System Permissions DevForums post
File Provider framework
Finder Sync framework
App Extension Programming Guide > App Extension Types > Finder Sync
Disk Arbitration Programming Guide
Mass Storage Device Driver Programming Guide
Device File Access Guide for Storage Devices
Apple File System Guide
TN1150 HFS Plus Volume Format
Extended Attributes and Zip Archives
File system changes introduced in iOS 17 DevForums post
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
File Provider
RSS for tagAllow other apps to access the documents and directories stored and managed by your containing app using File Provider.
Posts under File Provider tag
86 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I have created working fileprovider, that works perfectly on my local machine. Codesigned in xcode, with our company sign certificate as Developer ID Application. No provisioning profile. Also notarized result dmg.
Works as expected on my local machine. But won't load on any other machine.
Calling [NSFileProviderManager addDomain: ...], ends up with error:
Error Domain=NSFileProviderErrorDomain Code=-2001 "The application cannot be used right now." UserInfo={NSLocalizedDescription=The application cannot be used right now.}
Code=-2001 should mean, that no file provider manager extension was found in an app bundle.
I have made a TestFileProvider application that is totally simplified File Provider example.
This too does work only on my own machine.
Relevant code from app:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSFileProviderDomain* fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:@"com.xxxxx.dwc.FileProvider" displayName:@"TestDomain"];
[NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError * _Nullable error) {
if (error)
NSLog(@"add domain: %@", error);
else
NSLog(@"add domain SUCCESS");
}];
}
There are also these errors, that are related, but I do not understand what are they implying neither how to fix:
kernel Sandbox: fileproviderd(448) deny(1) file-read-data /Applications/TestFileProvider.app
fileproviderd [ERROR] PluginRecord doesn't have container url for
fileproviderd [WARNING] No provider found with identifier (null) for calling bundle (null) on second attempt.
I'm clueless on how to fix this. Is this related to codesign ? Or is it necessary to start fileprovider with different method call ?
Hey, I'm not sure I'm even in the correct ballpark - trying to allow my app to download largish videos from user's OneDrive and G-Drive to app
Is it correct to use NSFileCoordinator in this way?
How do I report progress as it downloads the video (is it possible?)
Is it correct to dismiss the picker like this?
anything else wrong (or, like is....any of it correct? :)
it's sort of working with my contrived examples (I created new personal G-drive / Onedrive accounts, and copied vids up there), but...when I use a file from our corporate OneDrive, from shared folder, I get:
"NSCocoaErrorDomain Code=3328 "The requested operation couldn’t be completed because the feature is not supported."
Is this the NSFileProvider extension (Microsoft's) complaining?
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
let isSecurityScoped = url.startAccessingSecurityScopedResource()
print("(#function) - iSecurityScoped = (isSecurityScoped)")
print("(#function) - document at (url)")
let filename = String(UUID().uuidString.suffix(6)) + "_" + url.lastPathComponent
let newURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(filename)
let readingIntent = NSFileAccessIntent.readingIntent(with: url, options: .withoutChanges)
fileCoordinator.coordinate(with: [readingIntent], queue: queue) { error in
defer {
if isSecurityScoped {
url.stopAccessingSecurityScopedResource()
}
}
if let error = error {
print("(#function) - (error)")
return
}
let safeURL = readingIntent.url
do {
let fileData = try Data(contentsOf: safeURL)
try fileData.write(to: newURL, options: .atomic)
print("(#function) - SUCCESS - newURL = (newURL)")
} catch {
print("(#function) - NOOOOO - (error)")
}
}
controller.dismiss(animated: true)
}
Trying to use file importer in a swift app to upload documents into firebase Storage and getting error when running on live device but works perfectly fine on emulator.
error:
BackgroundSession <***...> Failed to issue sandbox extension for file
file:///private/var/mobile/Library/Mobile%20Documents/comappleCloudDocs/Sample.pdf, errno = [1: Operation not permitted]
UNKNOWN ERROR Error Domain=FIRStorageErrorDomain Code=-13000 "An unknown error occurred, please check the server response." UserInfo={object=Repository/Sample.pdf, ResponseBody=Can not finalize upload. Current size is 0. Expected final size is 2665098., bucket=bucket, data={length = 77, bytes = 0x43616e20 6e6f7420 66696e61 6c697a65 ... 32363635 3039382e }, data_content_type=text/plain; charset=utf-8, NSLocalizedDescription=An unknown error occurred, please check the server response., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=400}
I tried separating all the logic from selectedFile.startAccessingSecurityScopedResource() all the way through the end into a function of its own using @MainActor based on another post I found around here and issue persisted..
Below is the implementation:
.fileImporter(
isPresented: $fileImporterIsPresented,
allowedContentTypes: [.pdf],
allowsMultipleSelection: false
) {
result in
switch result
{
case .success(let url):
print(url)
guard let selectedFile:URL = url.first else { return }
guard selectedFile.startAccessingSecurityScopedResource() else
{
return
}
let firebaseRepository = Storage.storage().reference().child("Repository/Sample.pdf")
let uploadTask = firebaseRepository.putFile(from: selectedFile)
uploadTask.observe(.progress)
{
snapshot in
// Upload reported progress
percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
/ Double(snapshot.progress!.totalUnitCount)
}
uploadTask.observe(.success)
{
snapshot in
selectedFile.stopAccessingSecurityScopedResource()
uploadTask.removeAllObservers()
print("SUCCESS")
// Upload completed successfully
}
uploadTask.observe(.failure)
{
snapshot in
if let error = snapshot.error as? NSError
{
switch (StorageErrorCode(rawValue: error.code)!)
{
case .objectNotFound:
print("NOT FOUND")
// File doesn't exist
break
case .unauthorized:
print("UNAUTHORIZED")
// User doesn't have permission to access file
break
case .cancelled:
print("CANCELLED")
// User canceled the upload
break
/* ... */
case .unknown:
print("UNKNOWN ERROR \(error.description)")
print("UNKNOWN ERROR \(error.localizedDescription)")
print("UNKNOWN ERROR \(error.underlyingErrors)")
// Unknown error occurred, inspect the server response
break
default:
print("UNSPECIFIED ERROR")
// A separate error occurred. This is a good place to retry the upload.
break
}
}
}
case .failure(let error):
print(error)
}
}
The existing project of Finder Extension is doing an amazing job in other paths but when I point it to the CloudStorage path the context menu doesn't show up. And no trace of what is going wrong any where (Xcode Logs, Console log, crash log, etc.)
Path Used:
/Users/<User>/Library/CloudStorage/FP-SomeDomains
Yes, even my first though was, it must be because of dataless file and folders. But unfortunately it not. There was no context menu presented from my Finder Extension even on real physical files and folders.
My project has a base app which is manually signed, inside I have a FileProvider parent app and extension.
When things works elegantly in Xcode debug build when I run FP App. But, when I package it, the FileProvider can't mount, fails with a generic error on parent app
(Error Domain=NSFileProviderErrorDomain Code=-2001 "The application cannot be used right now." UserInfo={NSLocalizedDescription=The application cannot be used right now.}
Another generic error in FileProvider demon
fileproviderd(488) deny(1) file-read-data /Applications/XYZ.app/Contents/Resources/FileFP.app
How to solve this?
I have a Login Item that is bundled with my .app and can run in the background. The Login Item has a File Provider extension. When a user downloads and installs a new version of the main .app, what's the correct way to handle stopping and restarting the login item and File Provider related processes to make sure they are running the latest code also?
I've been building a finder extension for managing a bunch of videos in a remote server. When I try to click on a video file that is dataless it seems to always trigger fetchContents(for:version:request:completionHandler:).
I have implemented fetchPartialContents(for:version:request:minimalRange:aligningTo:options:completionHandler:) but i haven't been able to trigger this method no matter how large the size of the file is. What are the conditions that i have to meet to trigger this function so i could stream the video data in chunks ?
I'm having an issue where adding new decorations to NSFileProviderDecorations doesn't make those decorations visible in the app.
Here is my NSFileProviderDecorations array in plist file:
<key>NSFileProviderDecorations</key>
<array>
<dict>
<key>BadgeImageType</key>
<string>com.apple.icon-decoration.badge.checkmark</string>
<key>Category</key>
<string>Badge</string>
<key>Identifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).iconSynced</string>
<key>Label</key>
<string>Synced</string>
</dict>
<dict>
<key>BadgeImageType</key>
<string>com.apple.icon-decoration.badge.warning</string>
<key>Category</key>
<string>Badge</string>
<key>Identifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).iconConflict</string>
<key>Label</key>
<string>In Conflict</string>
</dict>
<dict>
<key>BadgeImageType</key>
<string>com.apple.icon-decoration.badge.locked</string>
<key>Category</key>
<string>Badge</string>
<key>Identifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).iconLocked</string>
<key>Label</key>
<string>Locked</string>
</dict>
<dict>
<key>BadgeImageType</key>
<string>com.apple.icon-decoration.badge.warning</string>
<key>Category</key>
<string>Badge</string>
<key>Identifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).iconUploadFailed</string>
<key>Label</key>
<string>Upload failed</string>
</dict>
</array>
The first two decorations: iconSynced and iconConflict work just fine as expected, but then I added the other two decorations: iconLocked and iconUploadFailed and I just can't get them to work.
Here is an example of my decorations implementation:
var decorations: [NSFileProviderItemDecorationIdentifier]? {
[
entry.synced ? "iconSynced" : "",
entry.inConflict ? "iconConflict" : "",
entry.locked && !entry.uploadFailed ? "iconLocked" : "",
entry.uploadFailed ? "iconUploadFailed" : ""
].filter { !$0.isEmpty }.map {
NSFileProviderItemDecorationIdentifier(rawValue: "\(Bundle.main.bundleIdentifier!).\($0)")
}
}
What I tried:
Clear cache project and/or manually deleting Derived Data folder
Various combination changes and log prints to try to figure out what's wrong
Increasing Xcode project version
Computer restart
macOS: 12.6.5 (21G531)
Does anyone have the same issue or does anyone have an idea on how to resolve this? So, my problem is that I can't get the new badge decorations added to plist file to work (to be shown in Finder when reported from decorations callback).
https://developer.apple.com/documentation/fileprovider/nsfileproviderpartialcontentfetching/3923718-fetchpartialcontents
fetchPartialContents(for:version:request:minimalRange:aligningTo:options:completionHandler:)
I need to use this function to fetch contents of the files partially. But it seems I'm just unable to receive any callback when i try to open the file via double click on finder.
I've tried to open files of different types and sizes but still i'm defaulting back to fetchContents(for:version:request:completionHandler:) .
I've been thinking if there are any specific configurations or requirements that i have to meet , so i could trigger this callback function for all the fetch Operations for files ?
If No, then where am i going wrong ?
Hi.
By setting UISupportsDocumentBrowser to true in my app's Info.plist file, I can see this Setting option that allows the user to select the default save location for my app:
How can I access the value that the user has set here?
Hi there,
The first time an item is materialized (via fetchContents), the contents are downloaded and we set the contentVersion (to a hash of the content) - no problems here. Once a content change is made remotely, we enumerateChanges and change the contentVersion to ”empty” (Data()). This triggers fetchContents to be called (where we fetch the new content). As soon as we call the completion handler for fetchContents though (now with a new contentVersion (a hash of the new content), we get a call immediately after to modifyContents, with the same contents that we just fetched. This call to modifyContent seems like a bug. how can I prevent it from being called by the system?
Thanks for the help!
I'm working with NSFileProviderReplicatedExtension for macOS app. I want to apply default badge on files(For example, com.apple.icon-decoration.badge.warning, com.apple.icon-decoration.badge.pinned, .. etc).
I am unable to see any badge when I open the folder mounted by the Extension.
I've defined NSFileProviderDecorations in NSExtension as follows :
<dict>
<key>NSFileProviderDecorations</key>
<array>
<dict>
<key>BadgeImageType</key>
<string>com.apple.icon-decoration.pinned</string>
<key>Category</key>
<string>Badge</string>
<key>Identifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).cyfile</string>
<key>Label</key>
<string>CydriveFile</string>
</dict>
</array>
<key>NSExtensionFileProviderDocumentGroup</key>
<string>$(TeamIdentifierPrefix)com.example.app-group</string>
<key>NSExtensionFileProviderSupportsEnumeration</key>
<true/>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.fileprovider-nonui</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).FileProviderExtension</string>
</dict>
I have implemented the class Item that's implementing the following Protocols :
NSObject, NSFileProviderItemProtocol, NSFileProviderItemDecorating
and when returning decorations for that item I'm just doing this :
class Item : ... {
...
static let decorationPrefix = Bundle.main.bundleIdentifier!
static let heartItem = NSFileProviderItemDecorationIdentifier(rawValue: "\(decorationPrefix).cyfile")
var decorations: [NSFileProviderItemDecorationIdentifier]? {
var decos = [NSFileProviderItemDecorationIdentifier]()
decos.append(CyItem.heartItem)
return decos
}
}
As far as i can tell I've completed all the requirements for getting the badge to show up.
I'm trying to put a sub menu inside the context menu using the NSExtensionFileProviderActions in info.plist. Which should look like this image below
I have been trying to use FPUIActionExtensionViewController for doing this task but I havent got any context menu like above. But still doing that does seem to complicate the task more.
Is there a simpler way to do this task, like doing it within the info.plist so I dont have to complicate the task by creating a view controller. ?
I discovered a multithreading mistake in my use of NSManagedObjects recently and was surprised that I wasn't alerted to this during development, since I had -com.apple.CoreData.ConcurrencyDebug 1 set under "arguments passed on launch" for my macOS and iOS FileProvider extensions. I confirmed that the expected log stating CoreData: annotation: Core Data multi-threading assertions enabled. is NOT present when running these targets (but does appear as expected on my main macOS and iOS applications).
Can anyone advise me on how to get this concurrency debugging functionality to work on my FileProvider extension(s)?
Thanks
I'm asking this because the documentation is totally contradicting to itself on multiple occasions:
Extensions overview page (https://developer.apple.com/app-extensions/) claims it's not supported.
At the same time, on FileProviderUI docs page (https://developer.apple.com/documentation/fileproviderui) macOS is listed among another platforms and docs kinda generally suggest it is supported.
At the same time, "add new target" dialog in xcode is missing "File Provider UI Extension" template under macOS.
At the same time, it's can be easily be done by creating an iOS extension, then swapping SDK to macOS and UIKit APIs to their AppKit counterparts. This way, FileProviderUI actions DO appear in Finder.
Problem is, after clicking the action, UI never appears and here's what i see in Console:
default pkd Waiting on thread <private> until Launch Services database seeding is complete.
default Finder [d <private>] <PKHost:0x600000c38cc0> Beginning discovery for flags: 1024, point: (null)
default Finder [d <private>] <PKHost:0x600000c38cc0> Completed discovery. Final # of matches: 0
error Finder nil extension for provider ID (<private>), error: (null)
error Finder Action with identifier (<private>) did finish with error (Error Domain=FPUIActionViewControllerErrorDomain Code=1000).
error Finder FP Custom action sheet finished with error Error Domain=FPUIActionViewControllerErrorDomain Code=1000 "(null)"
default pkd [d <private>] Final plugin count: 0
This is totally confusing, please elaborate.
Is it possible to indirectly delete data stored in the stock iOS "File" app from any external app (without opening the File app)?
As reference information, we have confirmed that when data is deleted from a third-party file app (e.g. Readdle's documents(https://readdle.com/ja/documents) the data is also deleted from the genuine iOS file app.
We are implementing a file system extension using the file provider replicated extension for an application on Mac OS. On part of it, we need to show context menus for items(files/folders) inside the file provider's mounted folder.
But we don't want to show the context menu based on the 'activation rule' key's value declared on each NSExtensionFileProviderActions item in the info.plist file but with the main app's code logic. Because if we use the info.plist activation rule, we need to use each item's instance variables as part of predicate query(which decides on showing the context menu item), and after performing the action, we need to change the value of that instance variable so that we can show opposite context menu of the previous one (for example if previously 'set offline' is clicked, now 'set online' have to be shown) but doing this is tedious process.
Also, we already implemented the code logic in our main app(that is not written in swift) to choose what are the context menu items to be shown and so we want to use it.
So, Instead, we are hoping to do it either:
By handling the get-menu function call or
By handling the predicate checking function call.
Kindly let us know if is there any function we can override or inform the system to do at least any one of the above things.
Thanks in advance.
Currently, we are doing it by:
Calling the function 'signalEnumerator' with the identifier as workingset
Returning the metas of the new changes to the function enumerateChanges called by the file provider
Sometimes, it would take more time to get the enumerateChanges function call from the file provider after invoking the signalEnumerator function. So, Kindly let us know if is there any other alternative to pass the new updated items information to the file provider properly and quickly.
Previously, we are using the Finder Sync extension for showing the context menu on the finder items. But now we are planning to use the File Provider extension on Mac OS.
So, as of our learning, we found that the context menu items to be shown on the finder items have to be informed using the 'NSExtensionFileProviderActions' key in the info.plist file and the activation rule also have to be informed there under key 'NSExtensionFileProviderActionActivationRule'.
But in the Finder Sync, we can get both the right-click(to list menu) and menu item clicked(on the context menu shown) calls from the Finder Sync extension.
Like Finder Sync Extension, can we able to get both the calls from the file provider extension?