【问题标题】:SwiftUI With Local Notification Action带有本地通知操作的 SwiftUI
【发布时间】:2022-08-19 01:20:56
【问题描述】:

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

通知管理器类

    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()
    }
    
}
  • localNotificationDelegate 存储在属性中,因为一旦函数返回并在UNUserNotificationCenter 中清除它就会被删除,因为它在那里很弱。
  • 感谢“Asperi”它的工作知道,但是当我点击该动作时,它应该做出动作并关闭通知,但知道它会做出动作并打开应用程序。
  • 我喜欢如何在不打开应用程序的情况下对通知操作按钮进行操作,在堆栈溢出问题中的“在 iOS 中单击本地通知时不要打开应用程序”,您只需要删除“选项” \" 在创建操作按钮时的 \"UNNotificationAction\" 中。

标签: swift swiftui localnotification


【解决方案1】:

在与 SwiftUI 战斗 1 小时后,我的两分钱。 (注意:文档有点缺乏......)

  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) {
                completionHandler([.alert,.sound])
                
                let request = notification.request
                //let content = request.content
                let identifier = request.identifier
                //let title = content.title
                //print(title)
                print( identifier,"\n----\n")
                
                completionHandler([.alert,.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)
                
            }
            
        }
            
    }
    

【讨论】:

    猜你喜欢
    • 2020-06-09
    • 2021-08-19
    • 2022-10-04
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多