How do you allow arbitrary file selection in your own app?

I've written a little utility targeting Mac, for personal use. In it, I need to be able to select a file from an arbitrary location on my drive.

I have the "user selected file" entitlement added, and I have added my application to "Full Disk Access." But I still get a permissions error when I select a file with the file-open dialog (via .fileImporter).

I dragged the application from the Xcode build directory to Applications before adding it to Full Disk Access. Any ideas?

Answered by Stoked in 816453022

Thanks! That does work, with the slight addition of having to call that method on the URL returned by the file dialog. So my button to open a file in SwiftUI looks like:

		Button(action: { isImporting = true }, label: { Text("Open P8 file") })
			.fileImporter(isPresented: $isImporting,
						  allowedContentTypes: [.data],
						  onCompletion: { result in
				switch result
				{
				case .success(let theURL):
					do
					{
						let didStart = theURL.startAccessingSecurityScopedResource()
						defer
						{
							if didStart
							{
								theURL.stopAccessingSecurityScopedResource()
							}
						}
						secretKey = try String(contentsOf: theURL, encoding: .utf8)
						generateToken()
					}
					catch
					{
						message = error.localizedDescription
					}
				case .failure(let error):
					print(error)
				}
			})

I filed a bug report on the documentation.

Are you doing the {start,stop}AccessingSecurityScopedResource() dance? See Accessing files from the macOS App Sandbox for details.

Share and Enjoy

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

Thanks for the reply. I think I'm doing everything mentioned in that article. There doesn't seem to be anything to do immediately before presenting the File dialog:

The operating system implicitly starts security-scoped access on URLs passed from open panels, save panels, or items dragged to your app’s icon in the Dock

Accepted Answer

Regardless, do the {start,stop}AccessingSecurityScopedResource() dance. It won’t cause problems and it’ll be a useful test [1].

So, write your code like this:

let didStart = startAccessingSecurityScopedResource()
defer {
    if didStart {
        stopAccessingSecurityScopedResource()
    }
}
… read the file contents …

Share and Enjoy

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

[1] Accessing files from the macOS App Sandbox was written from the perspective of AppKit, and thus I’m not 100% confident that that quote applies to SwiftUI.

Thanks! That does work, with the slight addition of having to call that method on the URL returned by the file dialog. So my button to open a file in SwiftUI looks like:

		Button(action: { isImporting = true }, label: { Text("Open P8 file") })
			.fileImporter(isPresented: $isImporting,
						  allowedContentTypes: [.data],
						  onCompletion: { result in
				switch result
				{
				case .success(let theURL):
					do
					{
						let didStart = theURL.startAccessingSecurityScopedResource()
						defer
						{
							if didStart
							{
								theURL.stopAccessingSecurityScopedResource()
							}
						}
						secretKey = try String(contentsOf: theURL, encoding: .utf8)
						generateToken()
					}
					catch
					{
						message = error.localizedDescription
					}
				case .failure(let error):
					print(error)
				}
			})

I filed a bug report on the documentation.

with the slight addition of having to call that method on the URL returned by the file dialog

D’oh! That’ll teach me to post code without compiling it )-:

I filed a bug report on the documentation.

Thanks.

Please post your bug number, just for the record.

Share and Enjoy

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

NP, it got me to the answer!

The bug report is FB16031640

I attached a project to it to repro the problem.

How do you allow arbitrary file selection in your own app?
 
 
Q