This content originally appeared on Level Up Coding - Medium and was authored by Itsuki
While I was making my MacOS App, I run into the question: Why Cannot I read User Selected File?
There are lots of answers online suggesting things such a changing the permissions to read-write, give App Sandbox access to a specific directory or whatever, but I found it not being the cause for the problem above! At least not in my case!
Even with Sandbox enabled, we should be able to access user selected file by default as the following default entitlement file suggests.
But why we (at least I) could not?
Before I give out the answer, let’s see a short code snippet to get an idea of what I meant!
struct VideoSelectionView: View {
@State private var url: URL?
@State private var showImporter = false
var body: some View {
VStack(spacing: 32) {
if let url = url {
VideoPlayer(player: AVPlayer(url: url))
.padding(.bottom, 16)
.background(Color.black)
}
Button(action: {
showImporter = true
}, label: {
Text("Import!")
.font(.system(size: 32))
.foregroundStyle(.white)
.padding()
.frame(maxWidth: .infinity)
.background(RoundedRectangle(cornerRadius: 16).fill(Color.black))
})
}
.padding()
.frame(minWidth: 300, maxWidth: .infinity, minHeight: 200, maxHeight: .infinity)
.fileImporter(
isPresented: $showImporter,
allowedContentTypes: [.movie],
allowsMultipleSelection: false
) { result in
print("result: \(result)")
switch result {
case .success(let urls):
print("success url: \(urls)")
guard let url = urls.first else {return}
self.url = url
case .failure(let error):
print("failed with error: \(error.localizedDescription)")
}
}
}
}
As you can see, the import itself succeed since we are indeed getting an URL, but we our video is not playing!
I first thought that this might be caused by the incompatible URL format between the one obtained and the one required for VideoPlayer, because there is literally no error printed out anywhere!
However, I tried to read the data directly from the URL and find out that I am getting nil!
Time for the Solution!
Only ONE line needs to be added for everything to start working!
guard url.startAccessingSecurityScopedResource() else {return}
Yes, that’s it! Add it right before where we assign self.url = url.
It is quite common to call startAccessingSecurityScopedResource() when using UIKit but I probably never find a situation myself that I need to call this in SwiftUI while developing for iOS, at least not when importing files.
But this ends up being the key! And here we go!
Reminder
You might also want to revoke the access granted to the url on View disappear or when your task finishes by calling url?.stopAccessingSecurityScopedResource().
Thank you for reading!
Hope this article can give you some hints in solving similar issues!
Happy importing!
Swift/MacOS: Why Cannot We Read User Selected File? was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Itsuki
Itsuki | Sciencx (2024-08-15T18:04:16+00:00) Swift/MacOS: Why Cannot We Read User Selected File?. Retrieved from https://www.scien.cx/2024/08/15/swift-macos-why-cannot-we-read-user-selected-file/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.