具有本地通知操作的 SwiftUI

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

我使用这些两个类来管理应用程序中的本地通知,问题是当我点击通知操作按钮“标记为已完成”时,它没有执行该操作,只是将我带到应用程序,所以我如何才能使通知操作按钮响应该操作?

通知管理器类

    internal final class LocalNotificationManager {
        
        private static let center = UNUserNotificationCenter.current()
        
        // MARK: Ask for permission
        static func askUserPermissionToSendNotifications() {
            self.center.requestAuthorization(options: [.alert, .badge, .sound]) { (success, error) in
                if success {
                   // Do something if user allowing notifications
                } else if !success {
                    // Do something if user do not allow the notifications
                } else if let error = error {
                    // Show some message
                    print(error.localizedDescription)
                }
            }
        }
        
        // MARK: Schedul Notification
        static func schedulNotification(for taskModel: TaskModel) {
            
            let content = UNMutableNotificationContent()
            content.interruptionLevel = .timeSensitive
            content.body = taskModel.text
            content.subtitle = "\(taskModel.priority != .none ? "\(taskModel.priority.rawValue) Priority" : "")"
            content.categoryIdentifier = "Task Actions" // Same Identifier in registerCategories()
            content.sound = UNNotificationSound.default
            let taskIdentifier = taskModel.id.uuidString
                    
            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)      
            let request = UNNotificationRequest(identifier: taskIdentifier, content: content, trigger: trigger)

            let localNotificationDelegate = LocalNotificationDelegate()
            self.center.delegate = localNotificationDelegate
            
            let markAsCompleted = UNNotificationAction(identifier: "MARK_AS_COMPLETED", title: "Mark as Completed", options: .foreground)
            
            let placeholder = "Task"
            let category = UNNotificationCategory(identifier: "Task Actions", actions: [markAsCompleted], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: placeholder) // // Same Identifier in schedulNotification()
            
            self.center.setNotificationCategories([category])
            
            self.center.add(request)
        }
    }

通知委托

internal final class LocalNotificationDelegate: NSObject, ObservableObject, UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
        if response.actionIdentifier == "MARK_AS_COMPLETED" {
            // its didn't print the message when I tap the action button
            print("MARK_AS_COMPLETED Tapped")
        }
        completionHandler()
    }
    
}
swift swiftui localnotification
2个回答
2
投票

我花了 1 小时与 SwiftUI 对抗后的两分钱。 (注意:文档有点缺乏......)

  1. 没有委托,UserNotifications 不起作用。 (通常我们应该在心爱的旧 UIKIt 中使用 AppDelegate...)
  2. 对于应用程序委托,我们必须按照以下方式使用:

(坦克到https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app

@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
  1. 即便如此,没有“可选”委托调用它也不起作用..所以你必须至少实现:

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                 willPresent notification: UNNotification,
                                 withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    

现在是我的完整代码:(我知道并不总是很好,但对于初学者来说,只需复制/粘贴即可使其工作。)

我在通话中添加了一些注释和变体。

-- 应用程序 --

import SwiftUI

@main
struct LocalNotificationSwiftUIApp: App {
    
    // tanks to https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
    
    
    // app delegate:
    
    class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

            // print("Your code here")

            let nc = UNUserNotificationCenter.current()
            // if You do not set delegate, does not work.
            nc.delegate = self

            return true
        }
        
        
        // called after user has tapped on notification ballon.
        func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
            
            let request = notification.request
            //let content = request.content
            let identifier = request.identifier
            //let title = content.title
            //print(title)
            print( identifier,"\n----\n")
            
        completionHandler([.banner, .list, .badge, .sound])
        } // end of userNotificationCenter

    }
    
}

-- 内容视图

import SwiftUI
import UserNotifications


struct ContentView: View {
    var body: some View {
        VStack{
            Button("SCHEDULE", action: schedule)
        }
        .onAppear(perform: prepareForNotifications)
    }
    
    
    func prepareForNotifications(){

        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
            
            print("\(granted)")
            if granted {
                // run automatically... on run
                self.schedule()
            }
        }
    } // end of prepareForNotifications
    
    
    
    func schedule()  {
        
        let NOTIFICATION_DELAY  = 5.0             // if repeating, min is 60 secs.
        let NOTIFICATION_ID  = "NOTIFICATION_ID" // note: if repeating, ID must be differr, otherwise IOS will consider only once with this ID

        let USE_INTERVAL = true                 // experiment..

        let content = UNMutableNotificationContent()
        
        content.title = "Hello!"
        content.body = "Hello message body"
        content.sound = UNNotificationSound.default
        content.badge = 1
        
        let center = UNUserNotificationCenter.current()
                
        if USE_INTERVAL{
            
            let trigger = UNTimeIntervalNotificationTrigger.init(
                timeInterval: NOTIFICATION_DELAY,
                //repeats: true // if true, min 60 secs.
                repeats: false
            )
            
            let request = UNNotificationRequest.init(identifier: NOTIFICATION_ID,
                                                     content: content,
                                                     trigger: trigger)
            // Schedule the notification.
            center.add(request)
            
        }else{
            // USE DATE:
            
            let date = Date(timeIntervalSinceNow: 5)
            let triggerDate = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second,], from: date)
            let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate,
                                                        repeats: true)
            
            let request = UNNotificationRequest.init(identifier: NOTIFICATION_ID,
                                                     content: content,
                                                     trigger: trigger)
            // Schedule the notification.
            center.add(request)
            
        }
        
    }
        
}

0
投票

通过观看 Kavsoft 的视频,我能够向 SwiftUI 视图添加可操作的通知

struct ContentView: View {
    @StateObject var delegate = NotificationDelegate()
    var body: some View {
        Button(action: createNotification) {
            Text("Notify User")
        }
        .onAppear {
            UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
                
            }
            UNUserNotificationCenter.current().delegate = delegate
        }
        .alert(isPresented: $delegate.alert) {
            Alert(title: Text("Message"), message: Text("Reply Button is pressed"), dismissButton: .destructive(Text("Ok")))
        }
    }
    
    func createNotification() {
        let content = UNMutableNotificationContent()
        content.title = "Message"
        content.subtitle = "Hello, world!"
        content.categoryIdentifier = "ACTIONS"
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
        let request = UNNotificationRequest(identifier: "IN-APP", content: content, trigger: trigger)
        
        let close = UNNotificationAction(identifier: "CLOSE", title: "Close", options: .destructive)
        let reply = UNNotificationAction(identifier: "REPLY", title: "Reply", options: .foreground)
        
        let category = UNNotificationCategory(identifier: "ACTIONS", actions: [close, reply], intentIdentifiers: [])
        
        UNUserNotificationCenter.current().setNotificationCategories([category])
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
    }
}

class NotificationDelegate: NSObject, ObservableObject, UNUserNotificationCenterDelegate {
    @Published var alert = false
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.badge, .banner, .sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        if response.actionIdentifier == "REPLY" {
            print("reply or do something else")
            self.alert.toggle()
        }
        
        completionHandler()
    }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.