NSCocoaErrorDomain Code=257 file couldn’t be opened because you don’t have permission to view it : FileManager attributesOfItem returns nil in iOS13
iOS 13 SDK consider photo app as an another app, so when we dismiss the image picker controller video url will be invalidate.
I had the problem before when I try to upload video to AWS, what i did just create a temporary folder and copy the existing video url path before dismiss the Image-picker.then it upload, it's worked.
func createDirectory(videoURL:URL){
let Directorypath = getDirectoryPath()
var objcBool:ObjCBool = true
let isExist = FileManager.default.fileExists(atPath:Directorypath,isDirectory: &objcBool)
// If the folder with the given path doesn't exist already, create it
if isExist == false{
do{
try FileManager.default.createDirectory(atPath: Directorypath, withIntermediateDirectories: true, attributes: nil)
}catch{
print("Something went wrong while creating a new folder")
}
}
let fileManager = FileManager()
do {
if fileManager.fileExists(atPath:Directorypath) {
try? fileManager.removeItem(at: URL(fileURLWithPath:Directorypath))
}
try fileManager.copyItem(at:videoURL.absoluteURL, to: URL(fileURLWithPath:Directorypath))
self.imagePicker.dismiss(animated: true, completion:nil)
}catch let error {
print(error.localizedDescription)
}
}
How to access created Directory? - NSCocoaErrorDomain Code=257
You cannot move a file to a directory without appending the file name
do {
let fileName = localUrl.lastPathComponent
let offlineURL = offlinePath.appendingPathComponent(fileName)
try fileManager.moveItem(at: localUrl, to: offlineURL)
file.localUrl = offlineURL
} ...
The file couldn't be opened because there is no such file when getting FileAttributesKey - Swift
I could reproduce your issue with a simple Playground where I placed a resource called "hello.text".
Here are the results:
let filePath = Bundle.main.path(forResource: "hello", ofType: "txt")!
// Prints as /var/folders/blah-blah-blah/hello.txt
let fileURL = Bundle.main.url(forResource: "hello", withExtension: "txt")!
// Prints as file:///var/folders/blah-blah-blah/hello.txt
The issue is that the file://
prefix is specific to file's URL
and is not expected for path arguments of type String
.
try FileManager.default.attributesOfItem(atPath: fileURL.absoluteString) // ❌
try FileManager.default.attributesOfItem(atPath: fileURL.path) // ✅
Catch Error Reading File From Disk - You Don't Have Permissions
I'm less knowledgeable about exactly how this works on iOS, but I do have some knowledge about how it works for macOS, and the two should be similar. For macOS sandboxed apps the user has to select the file outside of the sandbox specifically via NSOpenPanel
or NSSavePanel
. The equivalent on iOS would be UIDocumentPickerViewController
, but I assume an explicit share would work too. Based on that, here's how I would think about it and what I would try, if I were faced with your problem:
You've got two URL
s involved in your call to FileManager.default.copy()
. It's not clear which one is producing the error, so I'll consider both.
First let's look at fileURL
. You're constructing it to put a file in the user's Documents
directory. On macOS at least, that directory is not in the app's sandbox, which means asking the user via NSSavePanel
(which also means they might decide to put it somewhere else). You might have to do the UIKit
equivalent, or just make sure you're picking a location that is in your sandbox.
To test that, instead of doing the copy, try writing to fileURL
to isolate just that one. For example:
do { try "TestString".data(using: .utf8)?.write(url: fileURL) }
catch { print("Write failed: \(error.localizedDescription)") }
If that fails, then your problem is with fileURL
, in which case you may need to use UIDocumentPickerViewController
to save it, or pick a location that's definitely in the app's sandbox.
If the test succeeds, the problem must be with the incoming URL
.
I'm going to assume that url
is already security scoped, because I'm not sure how sharing would even work otherwise. What I think is most likely happening behind the scenes is that when the user shares a URL
with your app, iOS creates a security-scoped bookmark from the URL
and sends the bookmark rather than the URL
to your app. Then on your app's end, that bookmark is used to reconstitute the URL
before passing it on to your app's delegate. If I'm right about that you'll need to open and close a security scope to use it:
url.startAccessingSecurityScopedResource()
// access your file here
url.stopAccessingSecurityScopedResource()
Note that stopAccessingSecurityScopeResource()
has to be called on the main thread, so if you're code is happening asynchronously you'll need to schedule it to run there:
url.startAccessingSecurityScopedResource()
// access your file here
DispatchQueue.main.async { url.stopAccessingSecurityScopedResource() }
If you need to save the URL
itself to use in a future run of your program... you can't. Well, you can, but it won't be valid, so you'll be right back to permissions errors. Instead you have to save a bookmark, and then in that future run, reconstruct the URL
from the bookmark.
let bookmark = try url.bookmarkData(
options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
bookmark
is an instance of Data
, so you can write that to UserDefaults
or wherever you might want to save it. To get a URL
back from it later:
var isStale = false
let url = try URL(
resolvingBookmarkData: bookmark,
options: .withSecurityScope,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)
if isStale
{
let newBookmark = try url.bookmarkData(
options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
// Save the new bookmark
}
Note that if isStale
is true
after the initializer returns, then you need to remake and resave the bookmark.
It's a shame that we have to go through this much trouble, but we live in a world where some people insist on doing bad things to other people's devices and data, so it's what we have to deal with the protect users from malicious data breaches.
FileManager returns url with Nil instead of file on it
Found apple documentation about getting access to directories. Edited my code to this and now it is working
guard urls.first!.startAccessingSecurityScopedResource() else {
print("Error getting access")
return
}
defer { urls.first!.stopAccessingSecurityScopedResource() }
let path = urls.first!.path
let stream = InputStream(url: URL(fileURLWithPath: path))
do {
let csv = try CSVReader(stream: stream!)
print("Everything is ok")
while let row = csv.next() {
print(row)
}
URL(fileURLWithPath: path).stopAccessingSecurityScopedResource()
} catch {
print(error)
}
Basically before working with the URL you get the request to use secured URL by this function
guard urls.first!.startAccessingSecurityScopedResource() else {
print("Error getting access")
return
}
defer { urls.first!.stopAccessingSecurityScopedResource() }
And end working with secured connection by writing this line
URL(fileURLWithPath: path).stopAccessingSecurityScopedResource()
However code written in documentation is not working for me, and error check(that i deleted) still giving me an error
Update
If code is not working, you can delete this line
defer { urls.first!.stopAccessingSecurityScopedResource() }
Related Topics
Cannot Assign to Value: 'Word' Is a 'Let' Constant
Is String Type a Class or a Struct? or Something Else
Hstack with Sf Symbols Image Not Aligned Centered
How to Create Text File for Writing
Swift Bindings Won't Work Xcode 6 Beta 5
How to Update Swift from 3.1 to 3.2, But Not to 4.0
Display All Available Wifi Connections with Swift in Os X
How to Open/View iOS Oslogs Stored on Device
How to List Swift Types That Conform to Protocol Using Reflection
Swiftui 2 Firebase Push Notification
Use 'Self' as a Default Parameter
How to Get Next Case of Enum(I.E. Write a Circulating Method) in Swift 4.2
Understanding Shorthand Closure Syntax for Map Function in Swift
Handle Swiftui and Corelocation with Mvvm-Pattern
What Is the Property Block Declaration Equivalent in Swift of the Following Block Property