Created
July 26, 2018 13:53
-
-
Save kayoslab/25531f4860afc0c2d1ab5f5c34317b61 to your computer and use it in GitHub Desktop.
Example implementation for a basic iOS 10 UNNotificationServiceExtension to handle jpg/gif/png files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UserNotifications | |
class NotificationService: UNNotificationServiceExtension { | |
var contentHandler: ((UNNotificationContent) -> Void)? | |
var bestAttemptContent: UNMutableNotificationContent? | |
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { | |
self.contentHandler = contentHandler | |
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) | |
guard let content = bestAttemptContent else { | |
#if DEBUG | |
exitGracefully("bestAttemptContent not a UNMutableNotificationContent") | |
#endif | |
return | |
} | |
DispatchQueue.main.async { [weak self] in | |
let userInfo: [AnyHashable: Any] = request.content.userInfo | |
content.attachments = self?.attachmentsFor(userInfo) ?? [] | |
guard let copy = self?.bestAttemptContent else { | |
#if DEBUG | |
self?.exitGracefully("bestAttemptContent is nil") | |
#endif | |
return | |
} | |
contentHandler(copy) | |
} | |
} | |
override func serviceExtensionTimeWillExpire() { | |
if let contentHandler = contentHandler, let content = self.bestAttemptContent { | |
contentHandler(content) | |
} | |
} | |
/// Helper function to extract Attachments from an userInfo object | |
/// | |
/// - Attribute userInfo: The user info extracted from the notification, | |
/// which should contain one of the available keys to create | |
/// a rich push notification. | |
private func attachmentsFor(_ userInfo: [AnyHashable: Any]) -> [UNNotificationAttachment] { | |
if let attachmentURLString = userInfo["image-url-png"] as? String { | |
guard let attachmentURL = URL(string: attachmentURLString), | |
let imageData = try? Data(contentsOf: attachmentURL), | |
let attachment = self.save("image.png", data: imageData, options: nil) else { | |
#if DEBUG | |
self.exitGracefully("PNG was not saved properly") | |
#endif | |
return [] | |
} | |
return [attachment] | |
} else if let attachmentURLString = userInfo["image-url-jpg"] as? String { | |
guard let attachmentURL = URL(string: attachmentURLString), | |
let imageData = try? Data(contentsOf: attachmentURL), | |
let attachment = self.save("image.jpg", data: imageData, options: nil) else { | |
#if DEBUG | |
self.exitGracefully("JPG was not saved properly") | |
#endif | |
return [] | |
} | |
return [attachment] | |
} else if let attachmentURLString = userInfo["image-url-gif"] as? String { | |
guard let attachmentURL = URL(string: attachmentURLString), | |
let imageData = try? Data(contentsOf: attachmentURL), | |
let attachment = self.save("image.gif", data: imageData, options: nil) else { | |
#if DEBUG | |
self.exitGracefully("GIF was not saved properly") | |
#endif | |
return [] | |
} | |
return [attachment] | |
} | |
return [] | |
} | |
/// Save data object onto disk and return an optional attachment linked to this path. | |
/// | |
/// - Attributes: | |
/// - identifier: The unique identifier of the attachment. | |
/// Use this string to identify the attachment later. If you specify an | |
/// empty string, this method creates a unique identifier string for you. | |
/// - data: The data stored onto disk. | |
/// - options: A dictionary of options related to the attached file. | |
/// Use the options to specify meta information about the attachment, | |
/// such as the clipping rectangle to use for the resulting thumbnail. | |
private func save(_ identifier: String, data: Data, options: [AnyHashable: Any]?) -> UNNotificationAttachment? { | |
// Create paths | |
let directory = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true) | |
let fileURL = directory.appendingPathComponent(identifier) | |
// Write data on disk | |
try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil) | |
try? data.write(to: fileURL, options: []) | |
// Create Notification attachment | |
return try? UNNotificationAttachment(identifier: identifier, url: fileURL, options: options) | |
} | |
/// Something went wrong, so maybe we want to clean up and present a fallback to the user. | |
/// | |
/// - Attribute reason: The reason why something went wrong. | |
private func exitGracefully(_ reason: String = "") { | |
guard let copy = bestAttemptContent?.mutableCopy() as? UNMutableNotificationContent else { return } | |
copy.title = reason | |
contentHandler?(copy) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment