I've been working on rich notification experience which has been introduced in iOS10 and stuck with passing images as attachments to UNNotificationContentExtension.
Here's my ContentExtension:
class NotificationViewController: UIViewController, UNNotificationContentExtension {
@IBOutlet weak var attachmentImage: UIImageView!
func didReceive(_ notification: UNNotification) {
if let attachment = notification.request.content.attachments.first {
if attachment.url.startAccessingSecurityScopedResource() {
attachmentImage.image = UIImage(contentsOfFile: attachment.url.path)
attachment.url.stopAccessingSecurityScopedResource()
}
}
}
}
As a tutorial, I've been following Advanced Notifications video from WWDC.
I've checked - UIImage I'm assigning to UIImageView:
nil
CGSize (191x191)/var/mobile/Library/SpringBoard/PushStore/Attachments/<bundle of app>/<...>.png
Here's how I send local notification from the app:
let content = UNMutableNotificationContent()
content.title = "Sample title"
content.body = "Sample body"
content.categoryIdentifier = "myNotificationCategory"
let attachement = try! UNNotificationAttachment(identifier: "image",
url: Bundle.main.url(forResource: "cat", withExtension: "png")!,
options: nil)
content.attachments = [ attachement ]
let request = UNNotificationRequest(identifier:requestIdentifier, content: content, trigger: nil)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request){(error) in
if (error != nil){
}
}
"cat.png" is just a dummy resource I've added to proj.

As you can see, notification shows the pic, so I assume, that I'm sending it correctly, but in the expanded state(in NotificationViewController) I've never succeed at showing the same image.
What am I doing wrong? Thanks!
When you create an UIImage with contentsOfFile, the UIImage object reads the image header only, which indicates basic info, such as image size, etc.
So, try move stopAccessingSecurityScopedResource to [NotificationViewController dealloc].
Or using following:
objective-c code:
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
swift code:
let imageData = NSData(contentsOf: attachment.url)
let image = UIImage(data: imageData! as Data)
There is no document saying that contentsOfFile only reads the image header. But when I run the following code:
NSString *docFolderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *pngPath = [docFolderPath stringByAppendingPathComponent:@"test.png"];
UIImage *image = [UIImage imageWithContentsOfFile:pngPath];
[[NSFileManager defaultManager] removeItemAtPath:pngPath error:nil];
imageView.image = image;
An error occurs:
ImageIO: createDataWithMappedFile:1322: 'open' failed '/Users/fanjie/Library/Developer/CoreSimulator/Devices/FFDFCA06-A75E-4B54-9FC2-8E2AAE3B1405/data/Containers/Data/Application/E2D26210-4A53-424E-9FE8-D522CFD4FD9E/Documents/test.png'
error = 2 (No such file or directory)
So I made a conclusion that UIImage contentsOfFile only reads the image header.
Thanks to @jeffery ,
Here is the exact code for the image shown in the notification extension:
if let attachment = notification.request.content.attachments.first {
if attachment.url.startAccessingSecurityScopedResource() {
let data = NSData(contentsOfFile: attachment.url.path);
self. attachmentImage?.image = UIImage(data: data! as Data);
attachment.url.stopAccessingSecurityScopedResource()
}
}
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