Dans mon Notification Service Extension
Je télécharge une image à partir d'une URL pour l'afficher sous la forme UNNotificationAttachment
dans une notification.
J'ai donc cette image en tant que UIImage et je ne vois pas la nécessité de l'écrire dans mon répertoire de répertoire d'application/conteneur de groupe sur le disque juste pour configurer la notification.
Existe-t-il un bon moyen de créer un UNNotificationAttachment
avec un UIImage? (devrait être applicable aux notifications locales et distantes)
NSData
du UIImage
dans le répertoire nouvellement crééJ'ai écrit une extension sur 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)
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
}
}
Donc pour créer UNUserNotificationRequest
avec UNUserNotificationAttachment
à partir d'un UIImage
vous pouvez simplement faire qc comme ceci
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 that follows the
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
}
Cela devrait fonctionner puisque UNNotificationAttachment
copiera le fichier image vers un emplacement propre.
J'ai créé un blog sur ce sujet, axé sur les images GIF. Mais il devrait être facile de réécrire mon code pour de simples images.
Vous devez créer une extension de service de notification:
Et incluez ce code:
final class NotificationService: UNNotificationServiceExtension {
private var contentHandler: ((UNNotificationContent) -> Void)?
private var bestAttemptContent: UNMutableNotificationContent?
override internal func didReceiveNotificationRequest(request: UNNotificationRequest, withContentHandler contentHandler: (UNNotificationContent) -> Void){
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
func failEarly() {
contentHandler(request.content)
}
guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
return failEarly()
}
guard let attachmentURL = content.userInfo["attachment-url"] as? String else {
return failEarly()
}
guard let imageData = NSData(contentsOfURL:NSURL(string: attachmentURL)!) else { return failEarly() }
guard let attachment = UNNotificationAttachment.create("image.gif", data: imageData, options: nil) else { return failEarly() }
content.attachments = [attachment]
contentHandler(content.copy() as! UNNotificationContent)
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original Push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
extension UNNotificationAttachment {
/// Save the image to disk
static func create(imageFileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
let fileManager = NSFileManager.defaultManager()
let tmpSubFolderName = NSProcessInfo.processInfo().globallyUniqueString
let tmpSubFolderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(tmpSubFolderName, isDirectory: true)
do {
try fileManager.createDirectoryAtURL(tmpSubFolderURL!, withIntermediateDirectories: true, attributes: nil)
let fileURL = tmpSubFolderURL?.URLByAppendingPathComponent(imageFileIdentifier)
try data.writeToURL(fileURL!, options: [])
let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, URL: fileURL!, options: options)
return imageAttachment
} catch let error {
print("error \(error)")
}
return nil
}
}
Pour plus d'informations, vous pouvez consulter mon blog ici: http://www.avanderlee.com/ios-10/rich-notifications-ios-10/
Voici un exemple complet sur la façon de télécharger une image sur Internet et de la joindre à une notification locale (qui fait partie de la question d'origine).
let content = UNMutableNotificationContent()
content.title = "This is a test"
content.body = "Just checking the walls"
if let url = URL(string: "https://example.com/images/example.png") {
let pathExtension = url.pathExtension
let task = URLSession.shared.downloadTask(with: url) { (result, response, error) in
if let result = result {
let identifier = ProcessInfo.processInfo.globallyUniqueString
let target = FileManager.default.temporaryDirectory.appendingPathComponent(identifier).appendingPathExtension(pathExtension)
do {
try FileManager.default.moveItem(at: result, to: target)
let attachment = try UNNotificationAttachment(identifier: identifier, url: target, options: nil)
content.attachments.append(attachment)
let notification = UNNotificationRequest(identifier: Date().description, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(notification, withCompletionHandler: { (error) in
if let error = error {
print(error.localizedDescription)
}
})
}
catch {
print(error.localizedDescription)
}
}
}
task.resume()
}
Normalement, il n'est pas nécessaire de recréer l'image lorsque le fichier téléchargé est déjà une image valide. Copiez simplement le fichier téléchargé dans le répertoire Temp actuel avec un nom unique et un .png
ou .jpg
extension. Il n'est pas non plus nécessaire de créer un sous-répertoire dans le répertoire Temp existant.