应用程序在后台时未收到本地通知

问题描述 投票:0回答:1

我集成了交互式本地通知。我使用 OpenAI 创建了一个聊天机器人。当应用程序在后台时,我想通过交互式本地通知与聊天机器人进行交互。 当用户响应交互式本地通知时,我通过以下函数收到用户响应。

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    if response.actionIdentifier == "replyAction" {
        if let textResponse = response as? UNTextInputNotificationResponse {
            userQueryText = textResponse.userText
            fetchGPTChatforResponse(prompt: userQueryText ?? "")
        }
    }
    completionHandler()
}

收到交互式通知的用户响应后,我调用以下函数:

func fetchGPTChatforResponse(prompt: String) {
    Task {
        do {
            let gptText = try await APIService().sendPromptToGPT(prompt: prompt)
            await MainActor.run {
                sendInteractiveNotification(message: gptText)
            }
        } catch {
            print("Errrror")
        }
    }
}

由于我的应用程序在后台,我收到以下错误:

nw_write_request_report [C2] 发送失败,错误“套接字未连接”

nw_read_request_report [C1] 接收失败,错误为“软件导致连接中止”sendPromptToGPT

并且没有触发本地通知。我还实现了这样的背景模式功能。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
                
          // Request notification permission
          UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
                    if granted {
                        print("Notification permission granted")
                    } else if let error = error {
                        print("Notification permission denied: \(error.localizedDescription)")
                    }
                }
                
                UNUserNotificationCenter.current().delegate = self
                let customCategory = createNotificationCategory()
    UNUserNotificationCenter.current().setNotificationCategories([customCategory])
                IQKeyboardManager.shared.enable = true
                registerBackgroundModes()
                return true
            }

    func registerBackgroundModes() {
            print("registerBackgroundModes")
            let appRefreshTaskId = "com.xyz.iOSApp.apprefresh"
            let appProcessingTaskId = "com.xyz.iOSApp.fetch"
    
            BGTaskScheduler.shared.register(forTaskWithIdentifier: appRefreshTaskId, using: nil) { task in
                    self.fetchGPTChatforResponse(prompt: self.userQueryText ?? "")
                    task.setTaskCompleted(success: true)
                    self.scheduleAppRefresh()
                }
    
            BGTaskScheduler.shared.register(forTaskWithIdentifier: appProcessingTaskId, using: nil) { task in
                //Logger.shared.info("[BGTASK] Perform bg processing \(appProcessingTaskId)")
                self.fetchGPTChatforResponse(prompt: self.userQueryText ?? "")
                task.setTaskCompleted(success: true)
                self.scheduleBackgroundProcessing()
    
            }
        }

func scheduleAppRefresh() {
    print("scheduleAppRefresh")
    let request = BGAppRefreshTaskRequest(identifier: "com.quilr.iOSApp.apprefresh")
    request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60)
    do {
        try BGTaskScheduler.shared.submit(request)
    } catch {
        print("Could not schedule app refresh task \(error.localizedDescription)")
    }
}

func scheduleBackgroundProcessing() {
    print("scheduleBackgroundProcessing")
    let request = BGProcessingTaskRequest(identifier: "com.quilr.iOSApp.fetch")
    request.requiresNetworkConnectivity = true // Need to true if your task need to network process. Defaults to false.
    request.requiresExternalPower = true // Need to true if your task requires a device connected to power source. Defaults to false.
    request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // Process after 5 minutes.
    do {
        try BGTaskScheduler.shared.submit(request)
    } catch {
        print("Could not schedule image fetch: (error)")
    }
}

在 SceneDelegate.swift 中,我调用后台刷新和后台处理函数,如下所示:

func sceneDidEnterBackground(_ scene: UIScene) {
    // Called as the scene transitions from the foreground to the background.
    // Use this method to save data, release shared resources, and store enough scene-specific state information
    // to restore the scene back to its current state.
    (UIApplication.shared.delegate as? AppDelegate)?.scheduleAppRefresh()
    (UIApplication.shared.delegate as? AppDelegate)?.scheduleBackgroundProcessing()
    // Save changes in the application's managed object context when the application transitions to the background.
    (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
}

我还通过添加功能启用了后台模式。但是当应用程序在后台时我仍然没有收到本地通知。

swift notifications background-process openai-api ios16
1个回答
0
投票

在完成工作之前,您正在调用提供给委托方法的

completionHandler
。这会导致 iOS 暂停您的应用程序,从而断开网络连接。

一旦

fetchGPTChatforResponse
完成其工作,您需要调用完成处理程序。

您可以消除

fetchGPTChatforResponse
函数,因为它本质上只是
sendPromptToGPT
的包装器并重构您的委托函数

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    Task {
        if response.actionIdentifier == "replyAction" {
            if let textResponse = response as? UNTextInputNotificationResponse {
                userQueryText = textResponse.userText
                do {
                    let gptText = try await APIService().sendPromptToGPT(prompt: prompt)
                    await MainActor.run {
                        sendInteractiveNotification(message: gptText)
                    }
                }
                catch {
                   print(error)
                }
            }
        }
        completionHandler()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.