My goal (besides learning how to write an iOS app extension) is to allow a user to share an image using the share button from a variety of apps including Photos and automatically rename them. Lastly then I want to save the image to the "documents" folder of the app for further use.
I'm having some problems trying to get the actual didSelectPost
portion working since it seems that, unlike Objective-C examples I've seen, the loadItem
operation returns a NSURL
instead of an UIImage
. When attempting to copy the NSUrl to my apps documents folder I get an error:
Error Domain=NSCocoaErrorDomain Code=260 "The file “IMG_0941.JPG” couldn’t be opened because there is no such file." UserInfo={NSFilePath=file:///var/mobile/Media/PhotoData/OutgoingTemp/B79263E5-9512-4317-9C5D-817D7EBEFA9A/RenderedPhoto/IMG_0941.JPG, NSUnderlyingError=0x283f89080 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
This happens when I push the share button on a photo in the "photos" app, tap my extension and then press the "post" button.
I get the same error regardless if it's running in a simulator or real device.
Here's my hacked together progress so far:
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
let inputItem = extensionContext?.inputItems.first as! NSExtensionItem
let attachment = inputItem.attachments!.first!
if attachment.hasItemConformingToTypeIdentifier(kUTTypeJPEG as String) {
attachment.loadItem(forTypeIdentifier: kUTTypeJPEG as String, options: nil) { data, error in
var image: UIImage?
if let someUrl = data as? NSURL {
do {
// a ends up being nil in both of these cases
let a = NSData(contentsOfFile: someUrl.absoluteString!)
image = UIImage(data: a as! Data)
// let a = try Data(contentsOf: someUrl)
// image = UIImage(contentsOfFile: someUrl.absoluteString)
} catch {
print(error)
}
} else if let someImage = data as? UIImage {
image = someImage
}
if let someImage = image {
guard let compressedImagePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent("theimage.jpg", isDirectory: false) else {
return
}
let compressedImageData = someImage.jpegData(compressionQuality: 1)
guard (try? compressedImageData?.write(to: compressedImagePath)) != nil else {
return
}
} else {
print("Bad share data")
}
}
}
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
Notice I'm casting the img
variable as an NSURL
. I've tried to cast it as a UIImage
but that throws an exception.
I have some other things I'd like to do to the image, like read it's EXIF data but for now this is what I have. Any suggestions would be great as I'm really struggling to wrap my head around and learn this environment.
Similar but unsuccessful posts I've tried, notice they are all Objective-C:
iOS Share Extension issue when sharing images from Photo library
Share image using share extension in ios8
How to add my app to the share sheet action
[edit] Matched the layout of one of the better answers, still with no luck.