My app is capable of writing multi-gigabyte images. I need a way to allow the user to do something with the full-resolution images (such as AirDrop). It does not appear possible to write the image to Photos since there may not be enough memory to read the whole image in RAM and as far as I can tell PhotoKit allows readonly access.
With UIActivityViewController I am able to copy the large images with a NSFileCoordinator, but only if I use an extension of .zip or .bin for the destination URL. The file is copied, but macOS thinks they are archives and not an image. After the file has been copied, changing the extension to .jpg on the Mac allows the copied image to be used, but that is less than an ideal user experience.
Zipping the image (that is already compressed) is not a viable solution since the whole image would need to be read to zip it, which may exceed the amount of memory available. Not to mention it is a total waste of time/power consumption. How can I allow a user to copy multi-gigabyte images from my app, and ideally with UIActivityViewController?
Here is the code that allows the image to be copied. If I don't use .zip or .bin for the destination URL, the image isn't copied, nothing happens, no errors reported.
func copyImage() {
let fm = FileManager.default
var archiveUrl: URL?
var error: NSError?
let imageProductURL = TDTDeviceUtilites.getDocumentUrl(
forFileName: "hugeImage.jpg")
let coordinator = NSFileCoordinator()
coordinator.coordinate(readingItemAt: imageProductURL,
options: [.forUploading],
error: &error) { (zipUrl) in
let tmpUrl = try! fm.url(
for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: zipUrl,
create: true
).appendingPathComponent("hugeImage.jpg.zip")
try! fm.moveItem(at: zipUrl, to: tmpUrl)
archiveUrl = tmpUrl
}
if let url = archiveUrl {
let avc = UIActivityViewController(activityItems: [url],
applicationActivities: nil)
present(avc, animated: true)
} else {
print(error)
}
}