swift 如何在应用程序未运行时调试远程推送通知并点击推送通知?

lnlaulya  于 12个月前  发布在  Swift
关注(0)|答案(4)|浏览(157)

当应用程序运行时,它收到推送通知,然后调用didReceive。

func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    )

字符串
因此,当调用上述委托时,我会使用收到的有效负载显示一个屏幕。这里没有问题。
当应用程序没有运行和用户点击通知,那么它应该呈现如上所述的相同屏幕。它不工作,因为我没有添加在didnashLaunchingWithOptions的代码。
然后,我添加了以下代码:

func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
         ......        
    
            
        if let userInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
         ......
        }
        
        return true
    }


但这是不工作,我不能调试,因为当在调试模式下,我必须从后台杀死应用程序,并点击通知,但在这种情况下,调试器不会工作.我尝试了替代方法,即.

let aps = remoteNotif["aps"] as? [AnyHashable: Any]
            let string = "\n Custom: \(String(describing: aps))"
            let string1 = "\n Custom: \(String(describing: remoteNotif))"

            DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
                if var topController = application.windows.first?.rootViewController {
                    while let presentedViewController = topController.presentedViewController {
                        topController = presentedViewController
                    }

                    let ac = UIAlertController(title: string1, message: string, preferredStyle: .alert)
                    ac.addAction(UIAlertAction(title: "OK", style: .default))
                    topController.present(ac, animated: true)
                }
            }


我该如何解决这个问题?

uubf1zoe

uubf1zoe1#

“但在这种情况下调试器不会工作”不正确!即使Xcode没有启动它,您也可以在启动时附加调试器。
编辑方案,然后在“运行”操作中,在“信息”下,单击“启动”,单击第二个单选按钮:“等待可执行文件启动”。运行应用程序;它不会启动。现在通过推送通知启动应用程序。调试器工作。

mm5n2pyu

mm5n2pyu2#

我已经通过实现sceneDelegate willConnectTo方法解决了这个问题。没有必要在didnesshLaunchingWithOptions中处理它

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//Remote notification response
   if let response = connectionOptions.notificationResponse{
        print(response.notification.request.content.userInfo)
   }

   ....
}

字符串
这就够

tyg4sfes

tyg4sfes3#

您必须创建一个NotificationServiceExtension并在那里处理有效负载
在XCode中,
1.选择您的项目
1.从左下角选择Add Target x1c 0d1x
1.添加通知服务扩展
然后尝试这样做。下面的代码是用于FCM的,但您可以根据自己的负载修改它。
例如-

import UserNotifications
import UIKit

class NotificationService: UNNotificationServiceExtension {
    
    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Modify the notification content here...
            bestAttemptContent.title = "\(bestAttemptContent.title)"
            
            guard let fcmOptions = bestAttemptContent.userInfo["fcm_options"] as? [String: Any] else {
                contentHandler(bestAttemptContent)
                return
            }
            
            guard let imageURLString = fcmOptions["image"] as? String else {
                contentHandler(bestAttemptContent)
                return
            }
            
            getMediaAttachment(for: imageURLString) { [weak self] (image, error) in
                guard let self = self,
                      let image = image,
                      let fileURL = self.saveImageAttachment(image: image, forIdentifier: "attachment.png")
                else {
//                    bestAttemptContent.body = "Error - \(String(describing: error))"
                    contentHandler(bestAttemptContent)
                    return
                }
                
                let imageAttachment = try? UNNotificationAttachment(
                    identifier: "image",
                    url: fileURL,
                    options: nil)
                
                if let imageAttachment = imageAttachment {
                    bestAttemptContent.attachments = [imageAttachment]
                }
                
                contentHandler(bestAttemptContent)
            }
        }
        
    }
    
    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)
        }
    }
    
    private func saveImageAttachment(image: UIImage, forIdentifier identifier: String) -> URL? {
        let tempDirectory = URL(fileURLWithPath: NSTemporaryDirectory())
        
        let directoryPath = tempDirectory.appendingPathComponent(
            ProcessInfo.processInfo.globallyUniqueString,
            isDirectory: true)
        
        do {
            try FileManager.default.createDirectory(
                at: directoryPath,
                withIntermediateDirectories: true,
                attributes: nil)
            
            let fileURL = directoryPath.appendingPathComponent(identifier)
            
            guard let imageData = image.pngData() else {
                return nil
            }
            
            try imageData.write(to: fileURL)
            return fileURL
        } catch {
            return nil
        }
    }
    
    private func getMediaAttachment(for urlString: String, completion: @escaping (UIImage?, Error?) -> Void) {
        guard let url = URL(string: urlString) else {
            completion(nil, NotificationError.cannotParseURL)
            return
        }
        
        ImageDownloader.shared.downloadImage(forURL: url) { (result) in
            switch result {
            case .success(let image):
                completion(image, nil)
            case .failure(let error):
                completion(nil, error)
            }
        }
    }
    
}

enum NotificationError: Error {
    case cannotParseURL
}

字符串

gupuwyp2

gupuwyp24#

将您的启动从自动更改为等待可执行文件启动,您应该能够在应用未运行时调试通知。

相关问题