Seto
Seto

Reputation: 1646

Rewrite `UNNotificationServiceExtension` sub class into Swift 6 async await notation

I'm trying to rewrite a Swift code to Swift 6 language mode and am stuck with this problem. How do I safely pass the bestAttemptContent and contentHandler to the Task? This is from the UNNotificationServiceExtension subclass.

final class NotificationService: UNNotificationServiceExtension {

  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?
  var customNotificationTask: Task<Void, Error>?

  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    guard let bestAttemptContent = bestAttemptContent else {

      invokeContentHandler(with: request.content)
      return
    }

    do {
      let notificationModel = try PushNotificationUserInfo(data: request.content.userInfo)
      guard let templatedImageUrl = notificationModel.templatedImageUrlString,
            let imageUrl = imageUrl(from: templatedImageUrl) else {
        invokeContentHandler(with: bestAttemptContent)
        return
      }
      setupCustomNotificationTask(
        imageUrl: imageUrl,
        bestAttemptContent: bestAttemptContent,
        contentHandler: contentHandler
      )
    } catch {
      invokeContentHandler(with: bestAttemptContent)
    }
  }

  // More code

  private func downloadImageTask(
        imageUrl: URL,
        bestAttemptContent: UNMutableNotificationContent,
        contentHandler: @escaping (UNNotificationContent) -> Void
  ) {
        self.customNotificationTask = Task {
          let (location, _) = try await URLSession.shared.download(from: imageUrl)
          let desiredLocation = URL(fileURLWithPath: "\(location.path)\(imageUrl.lastPathComponent)")
          
            try FileManager.default.moveItem(at: location, to: desiredLocation)
            let attachment = try UNNotificationAttachment(identifier: imageUrl.absoluteString, url: desiredLocation, options: nil)
          bestAttemptContent.attachments = [attachment]
          contentHandler(bestAttemptContent)
        }
   }
}

I tried using the MainActor.run {}, but it just moved the error to that run function.

I also tried the new consuming keyword in the downloadImageTask. It silences the compiler and crashes during compilation. I thought it was a bug in Xcode 16.1, but I tried the code with Xcode 16.2, and it still crashes. Or is it impossible to use that keyword because UNMutableNotificationContent is a reference type? But the compiler should complain about that.

Any pointers?

Upvotes: 0

Views: 77

Answers (0)

Related Questions