SwiftUI:如何使通知交互更改为我的视图的一部分?

Posted

技术标签:

【中文标题】SwiftUI:如何使通知交互更改为我的视图的一部分?【英文标题】:SwiftUI: How can I make a notification interaction change part of my view? 【发布时间】:2021-10-30 20:58:02 【问题描述】:

我是 SwiftUI 新手,需要一些帮助。我正在构建一个应用程序,我希望用户与通知进行交互。如果他们“好的”通知,我希望它改变我的部分观点,在这种情况下,只是一个随着每个“好的”而上升的计数器。 我遇到的问题是我不能 @State var notificationCounter 在视图之外,所以它不会自动更新视图。但是,当我在视图中输入 @State var notificationCounter 时,我的 func userNotificationCenter 由于范围而无法访问该变量。 我该如何解决这个问题?

这是我目前所拥有的:

import SwiftUI
import UserNotifications

var notificationCounter = 0
struct HomeScreenView: View 
//    @State var notificationCounter = 0
    @State var delegate = NotificationDelegate()
    var body: some View 
            ZStack 
            Color("Nice Green")
                .ignoresSafeArea()
            VStack 
                Button(action:
                        createNotification, 
                       label: 
                    Text("Notify User")
                )
                .onAppear(perform:  //request permissions
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) (_,_) in
                    
                    
                    UNUserNotificationCenter.current().delegate = delegate
                )
                Text("Notification Interactions \(notificationCounter)")
            
                
    
    
    func createNotification() 
        let content = UNMutableNotificationContent()
        content.title = "God of Posture"
        content.subtitle = "Straighten Your Neck"
        content.categoryIdentifier = "Actions"
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 4, repeats: false)
        let request = UNNotificationRequest(identifier: "In-App", content: content, trigger: trigger)
        
        //notification actions
        let close = UNNotificationAction(identifier: "Close", title: "Close", options: .destructive)
        let okay = UNNotificationAction(identifier: "Okay", title: "Okay", options: .destructive)
        let category = UNNotificationCategory(identifier: "Actions", actions: [close, okay], intentIdentifiers: [], options: [])
        
        UNUserNotificationCenter.current().setNotificationCategories([category])
        
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
    
    




struct HomeScreenView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView().previewDevice(PreviewDevice(rawValue: "iPhone X"))
    



class NotificationDelegate: NSObject, ObservableObject, UNUserNotificationCenterDelegate 

    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 == "Okay" 
            print("Hello")
            print("counter is " + String(notificationCounter))
            notificationCounter = notificationCounter + 1
            print("counter is now " + String(notificationCounter))
        
        completionHandler()
        
    

【问题讨论】:

【参考方案1】:

最简单的解决方案是在您的NotificationDelegate 上创建一个@Published 属性(顺便说一下,应该是@StateObject,而不是@State)。

struct HomeScreenView: View 
    @StateObject var delegate = NotificationDelegate()
    
    var body: some View 
        ZStack 
            Color("Nice Green")
                .ignoresSafeArea()
            VStack 
                Button(action: delegate.createNotification) 
                    Text("Notify User")
                
                .onAppear 
                    delegate.requestAuthorization()
                
                Text("Notification Interactions \(delegate.notificationCounter)")
            
        
    


class NotificationDelegate: NSObject, ObservableObject, UNUserNotificationCenterDelegate 
    
    @Published var notificationCounter = 0
    
    override init() 
        super.init()
        UNUserNotificationCenter.current().delegate = self
    
    
    func requestAuthorization() 
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) (_,_) in
        
    
    
    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 == "Okay" 
            print("Hello")
            print("counter is " + String(notificationCounter))
            notificationCounter = notificationCounter + 1
            print("counter is now " + String(notificationCounter))
        
        completionHandler()
    
    
    func createNotification() 
        let content = UNMutableNotificationContent()
        content.title = "God of Posture"
        content.subtitle = "Straighten Your Neck"
        content.categoryIdentifier = "Actions"
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 4, repeats: false)
        let request = UNNotificationRequest(identifier: "In-App", content: content, trigger: trigger)
        
        //notification actions
        let close = UNNotificationAction(identifier: "Close", title: "Close", options: .destructive)
        let okay = UNNotificationAction(identifier: "Okay", title: "Okay", options: .destructive)
        let category = UNNotificationCategory(identifier: "Actions", actions: [close, okay], intentIdentifiers: [], options: [])
        
        UNUserNotificationCenter.current().setNotificationCategories([category])
        
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
    

【讨论】:

以上是关于SwiftUI:如何使通知交互更改为我的视图的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以将视图从 swiftUI 更改为 UIKit?

SwiftUI:如何使 TextField 适合多行内容?

SwiftUI:如何使 TextField 适合多行内容?

如何使我的 SwiftUI 网格视图正常工作?

如何在 SwiftUI 中使视图的高度从 0 动画到高度?

如何将 SwiftUI 状态从特定值更改为新状态值设置动画?