I have an iOS application that uses UIDocumentPickerController to present the user with a dialog where they can pick the location of a directory containing files for upload
This is working just fine in most cases but if they pick a directory that is located on their iCloud account, DocumentPickerViewController returns a URL that produces unusable file URLs when enumerating the iCloud directory
Here is how I set it up:
var documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypeFolder as String], in: .open)
documentPicker.delegate = self
sView.present(documentPicker, animated: true, completion: nil)
And here is how I enumerate the files in the iCloud directory that they have chosen:
NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (url) in
let access = url.startAccessingSecurityScopedResource()
var directoryContents: [URL]
do {
let keys : [URLResourceKey] = [.nameKey, .isDirectoryKey]
directoryContents = try FileManager.default.contentsOfDirectory(
at: url,
includingPropertiesForKeys: keys)
} catch {
print("error \(error))")
if access {
url.stopAccessingSecurityScopedResource()
}
return
}
if access {
url.stopAccessingSecurityScopedResource()
}
}
For each file, I pass it to FileManager to copy into the application's sandbox:
for fromURL in directoryContents {
var lastPath = fromURL.lastPathComponent
print("Lastpath is \(lastPath)")
let toURL: URL = documentURL.appendingPathComponent(lastPath)
print("fromURL - \(fromURL)")
print("toURL \(toURL)")
let fM = FileManager.default
if(fM.fileExists(atPath: toURL.path)) {
exists += 1
} else {
do {
let access = url.startAccessingSecurityScopedResource()
try fM.copyItem(at: fromURL, to: toURL)
if access {
url.stopAccessingSecurityScopedResource()
}
count += 1
} catch {
print("Error on file copy \(error)")
}
}
}
This works just fine if the directory is on, say, an external USB drive but if I point it to iCloud, this is what I get:
fromURL - file:///Users/greg/Library/Developer/CoreSimulator/Devices/FFDED20B-B142-4FC6-BA8F-C1DC193E2AB7/data/Library/Mobile%20Documents/com~apple~CloudDocs/Savvy/SavvyLink/SmallEngineDataRepo/.Flt0002_20180913P.csv.icloud
toURL file:///Users/greg/Library/Developer/CoreSimulator/Devices/FFDED20B-B142-4FC6-BA8F-C1DC193E2AB7/data/Containers/Data/Application/167AC69D-494C-4CB1-8A36-E230C5303F30/Documents/.Flt0002_20180913P.csv.icloud
Note the file names have a dot (.) prepended and a .iCloud postpended. If I look in my application's sandbox I see the files in the Documents directory but the contents of the files are NOT the contents of the files on iCloud but instead look to be themselves some kind of a URL
Thanks for any insight into what is going on here and what I am missing
What I expect to happen is to be able to take the URLs returned when enumerating the files in the iCloud directory and then pass those URLs to FileManager.copyItems to copy them into my application's sandbox
As I said, this works just fine for directories located on (say) USB drives but when used for directories on iCloud it results in copying in files with very different contents than what is on the original files in iCloud and with names changed to have a "." prepended and ".iCloud" postpended