UNNotificationAttachment with UIImage or Remote URL
- create directory in tmp folder
- write the
NSData
representation of theUIImage
into the newly created directory - create the UNNotificationAttachment with url to the file in tmp folder
- clean up tmp folder
I wrote an extension on UINotificationAttachment
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)
let imageData = UIImage.pngData(image)
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
}
}
So to create UNUserNotificationRequest
with UNUserNotificationAttachment
from a UIImage
you can simply do sth like this
let identifier = ProcessInfo.processInfo.globallyUniqueString
let content = UNMutableNotificationContent()
content.title = "Hello"
content.body = "World"
if let attachment = UNNotificationAttachment.create(identifier: identifier, image: myImage, options: nil) {
// where myImage is any UIImage
content.attachments = [attachment]
}
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 120.0, repeats: false)
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
// handle error
}
This should work since UNNotificationAttachment
will copy the image file to an own location.
Attach image to notification given image URL
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. URLSession
s use GCD to perform asynchronous networking.
UNNotificationAttachment failing to attach image
I have found the real issue behind it. In apple documentation it is written that the url should be a file url and because of which you might be facing issue.
To solve this I have added image to temporary directory and then added to UNNotificationAttachment
.
Please find the code below. (For my use case I was getting an imageURL)
extension UNNotificationAttachment {
/// Save the image to disk
static func create(imageFileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
let fileManager = FileManager.default
let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
let tmpSubFolderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
do {
try fileManager.createDirectory(at: tmpSubFolderURL!, withIntermediateDirectories: true, attributes: nil)
let fileURL = tmpSubFolderURL?.appendingPathComponent(imageFileIdentifier)
try data.write(to: fileURL!, options: [])
let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, url: fileURL!, options: options)
return imageAttachment
} catch let error {
print("error \(error)")
}
return nil
}
}
data in the argument of this function is Data of image . Below is how did I call this method.
let imageData = NSData(contentsOf: url)
guard let attachment = UNNotificationAttachment.create(imageFileIdentifier: "img.jpeg", data: imageData!, options: nil) else { return }
bestAttemptContent?.attachments = [attachment]
Related Topics
Constant Movement in Spritekit
Ios: One Ibaction for Multiple Buttons
Present a Modal View Controller with Transparent Background
Calling Performseguewithidentifier Doesn't Call Shouldperformseguewithidentifier
Not Receiving Push Notifications from Firebase
Urlresponse Is Not Retrieved After Storing in Cache Using Storecachedresponse
Uicellview Cell Layout in Swift
Hide the Cursor of a Uitextfield
iOS Multiline Label in Interface Builder
Get Pixel Value from Cvpixelbufferref in Swift
Apple Push Notification Limitation
iPhone Storage in Tmp Directory
Adding Unlimited Lines in a Text (Swiftui)
Exit Application When Click Button - iOS
Customize Apps Gallery in Appstore Page