使用 async 调整NotificationService代码。

This commit is contained in:
Fin 2021-12-15 14:25:10 +08:00
parent 51c01bae15
commit 89d9cbb020

View File

@ -13,7 +13,6 @@ import RealmSwift
import UIKit
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> ())?
lazy var realm: Realm? = {
let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark")
@ -85,164 +84,155 @@ class NotificationService: UNNotificationServiceExtension {
}
}
///
///
/// - Parameters:
/// - userInfo:
/// - bestAttemptContent: content
/// - completion:
fileprivate func downloadImage(_ imageUrl: String, completion: @escaping (_ imageFileUrl: String?) -> ()) {
/// - cache: 使
/// - data: Data
/// - key: Key
func storeImage(cache: ImageCache, data: Data, key: String) async {
return await withCheckedContinuation { continuation in
cache.storeToDisk(data, forKey: key, expiration: StorageExpiration.never) { _ in
continuation.resume()
}
}
}
/// 使 Kingfisher.ImageDownloader
/// - Parameter url: URL
/// - Returns: Result
func downloadImage(url: URL) async -> Result<ImageLoadingResult, KingfisherError> {
return await withCheckedContinuation { continuation in
Kingfisher.ImageDownloader.default.downloadImage(with: url, options: nil) { result in
continuation.resume(returning: result)
}
}
}
///
/// - Parameter imageUrl: URL
/// - Returns: ` File URL`
fileprivate func downloadImage(_ imageUrl: String) async -> String? {
guard let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark"),
let cache = try? ImageCache(name: "shared", cacheDirectoryURL: groupUrl),
let imageResource = URL(string: imageUrl)
else {
completion(nil)
return
}
func downloadFinished() {
let cacheFileUrl = cache.cachePath(forKey: imageResource.cacheKey)
completion(cacheFileUrl)
return nil
}
//
if cache.diskStorage.isCached(forKey: imageResource.cacheKey) {
downloadFinished()
return
return cache.cachePath(forKey: imageResource.cacheKey)
}
//
Kingfisher.ImageDownloader.default.downloadImage(with: imageResource, options: nil) { result in
guard let result = try? result.get() else {
completion(nil)
return
}
//
cache.storeToDisk(result.originalData, forKey: imageResource.cacheKey, expiration: StorageExpiration.never) { _ in
downloadFinished()
}
guard let result = try? await downloadImage(url: imageResource).get() else {
return nil
}
//
await storeImage(cache: cache, data: result.originalData, key: imageResource.cacheKey)
return cache.cachePath(forKey: imageResource.cacheKey)
}
///
/// - Parameters:
/// - bestAttemptContent: content
/// - completion:
fileprivate func setImage(content bestAttemptContent: UNMutableNotificationContent,
completion: @escaping (_ content: UNMutableNotificationContent) -> ())
{
/// Notification Content
/// - Parameter bestAttemptContent: Notification Content
/// - Returns: Notification Content
fileprivate func setImage(content bestAttemptContent: UNMutableNotificationContent) async -> UNMutableNotificationContent {
let userInfo = bestAttemptContent.userInfo
guard let imageUrl = userInfo["image"] as? String else {
completion(bestAttemptContent)
return
guard let imageUrl = userInfo["image"] as? String,
let imageFileUrl = await downloadImage(imageUrl)
else {
return bestAttemptContent
}
func finished(_ imageFileUrl: String?) {
guard let imageFileUrl = imageFileUrl else {
completion(bestAttemptContent)
return
let copyDestUrl = URL(fileURLWithPath: imageFileUrl).appendingPathExtension(".tmp")
// 使
try? FileManager.default.copyItem(
at: URL(fileURLWithPath: imageFileUrl),
to: copyDestUrl
)
if let attachment = try? UNNotificationAttachment(
identifier: "image",
url: copyDestUrl,
options: [UNNotificationAttachmentOptionsTypeHintKey: kUTTypePNG]
) {
bestAttemptContent.attachments = [attachment]
}
return bestAttemptContent
}
/// Notification Content ICON
/// - Parameter bestAttemptContent: Notification Content
/// - Returns: ICON Notification Content
fileprivate func setIcon(content bestAttemptContent: UNMutableNotificationContent) async -> UNMutableNotificationContent {
if #available(iOSApplicationExtension 15.0, *) {
let userInfo = bestAttemptContent.userInfo
guard let imageUrl = userInfo["icon"] as? String,
let imageFileUrl = await downloadImage(imageUrl)
else {
return bestAttemptContent
}
let copyDestUrl = URL(fileURLWithPath: imageFileUrl).appendingPathExtension(".tmp")
// 使
try? FileManager.default.copyItem(
at: URL(fileURLWithPath: imageFileUrl),
to: copyDestUrl
var personNameComponents = PersonNameComponents()
personNameComponents.nickname = bestAttemptContent.title
let avatar = INImage(imageData: NSData(contentsOfFile: imageFileUrl)! as Data)
let senderPerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: personNameComponents,
displayName: personNameComponents.nickname,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil,
isMe: false,
suggestionType: .none
)
let mePerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: nil,
displayName: nil,
image: nil,
contactIdentifier: nil,
customIdentifier: nil,
isMe: true,
suggestionType: .none
)
if let attachment = try? UNNotificationAttachment(
identifier: "image",
url: copyDestUrl,
options: [UNNotificationAttachmentOptionsTypeHintKey: kUTTypePNG]
) {
bestAttemptContent.attachments = [attachment]
}
completion(bestAttemptContent)
}
downloadImage(imageUrl, completion: finished)
}
/// icon
/// - Parameters:
/// - bestAttemptContent: content
/// - completion:
fileprivate func setIcon(content bestAttemptContent: UNMutableNotificationContent,
completion: @escaping (_ content: UNMutableNotificationContent) -> ())
{
if #available(iOSApplicationExtension 15.0, *) {
let userInfo = bestAttemptContent.userInfo
guard let imageUrl = userInfo["icon"] as? String else {
completion(bestAttemptContent)
return
}
let intent = INSendMessageIntent(
recipients: [mePerson],
outgoingMessageType: .outgoingMessageText,
content: bestAttemptContent.body,
speakableGroupName: INSpeakableString(spokenPhrase: personNameComponents.nickname ?? ""),
conversationIdentifier: bestAttemptContent.threadIdentifier,
serviceName: nil,
sender: senderPerson,
attachments: nil
)
func finished(_ imageFileUrl: String?) {
guard let imageFileUrl = imageFileUrl else {
completion(bestAttemptContent)
return
}
var personNameComponents = PersonNameComponents()
personNameComponents.nickname = bestAttemptContent.title
let avatar = INImage(imageData: NSData(contentsOfFile: imageFileUrl)! as Data)
let senderPerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: personNameComponents,
displayName: personNameComponents.nickname,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil,
isMe: false,
suggestionType: .none
)
let mePerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: nil,
displayName: nil,
image: nil,
contactIdentifier: nil,
customIdentifier: nil,
isMe: true,
suggestionType: .none
)
let intent = INSendMessageIntent(
recipients: [mePerson],
outgoingMessageType: .outgoingMessageText,
content: bestAttemptContent.body,
speakableGroupName: INSpeakableString(spokenPhrase: personNameComponents.nickname ?? ""),
conversationIdentifier: bestAttemptContent.threadIdentifier,
serviceName: nil,
sender: senderPerson,
attachments: nil
)
intent.setImage(avatar, forParameterNamed: \.sender)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming
interaction.donate(completion: nil)
do {
let content = try bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent
completion(content)
}
catch {
// Handle error
}
completion(bestAttemptContent)
}
intent.setImage(avatar, forParameterNamed: \.sender)
downloadImage(imageUrl, completion: finished)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming
try? await interaction.donate()
do {
let content = try bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent
return content
}
catch {}
return bestAttemptContent
}
else {
completion(bestAttemptContent)
return bestAttemptContent
}
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> ()) {
self.contentHandler = contentHandler
guard let bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
contentHandler(request.content)
return
@ -271,14 +261,16 @@ class NotificationService: UNNotificationServiceExtension {
//
autoCopy(userInfo, defaultCopy: bestAttemptContent.body)
//
archive(userInfo)
//
setIcon(content: bestAttemptContent) { result in
Task.init {
//
let iconResult = await setIcon(content: bestAttemptContent)
//
self.setImage(content: result) { result in
contentHandler(result)
}
let imageResult = await self.setImage(content: iconResult)
contentHandler(imageResult)
}
}
}