I want to attach an image to my local notifications given an image URL. This is the extension to create an attachment:
import UserNotifications
extension UNNotificationAttachment {
static func create(identifier: String, image: UIImage, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
let fileManager = FileManager.default
let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
let tmpSubFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
do {
try fileManager.createDirectory(at: tmpSubFolderURL, withIntermediateDirectories: true, attributes: nil)
let imageFileIdentifier = identifier+".png"
let fileURL = tmpSubFolderURL.appendingPathComponent(imageFileIdentifier)
guard let imageData = UIImagePNGRepresentation(image) else {
return nil
}
try imageData.write(to: fileURL)
let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, url: fileURL, options: options)
return imageAttachment } catch {
print("error " + error.localizedDescription)
}
return nil
}
}
When I schedule a new notification, I use it like this:
// url of the image such as http://www.unsplash.com/image.png
let data = try? Data(contentsOf: url)
guard let myImage = UIImage(data: data!) else { return }
if let attachment = UNNotificationAttachment.create(identifier: key, image: myImage, options: nil) {
content.attachments = [attachment]
}

Creating a notification like this freezes the application for a few seconds because the app downloads the image synchronously. I have also tried to use DispatchQueue but it didn't change anything. What did I do wrong?
Your code downloads an image, parses it to create a UIImage, converts the image back to a block of PNG data, then writes this data to a temporary file.
You can skip the step where you create the UIImage and convert it back to a file.
Try using URLSession and URLDataTask:
let fileURL = ...
let task = URLSession.shared.dataTask(with: url) { (data, _, _) in
do {
try imageData.write(to: fileURL)
let attachment = UNNotificationAttachment.create(identifier: key, image: myImage, options: nil)
// call closure to call back with attachment and/or error
}
catch let ex {
// call closure with error
}
}
task.resume()
I've left out some error handling and other details, but this should give you the general idea of what's required to do it asynchronously. URLSessions use GCD to perform asynchronous networking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With