我集成了交互式本地通知。我使用 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()
}
我还通过添加功能启用了后台模式。但是当应用程序在后台时我仍然没有收到本地通知。
在完成工作之前,您正在调用提供给委托方法的
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()
}
}