繁体   English   中英

在 onAppear() 方法中调用异步方法 (getNotificationSettings) 变为 nil - SwiftUI MVVM

[英]Calling an asynchronous method (getNotificationSettings) in the onAppear() method becomes nil - SwiftUI MVVM

我有一个NotificationsManager class 来管理所有与通知相关的代码,包括检查用户是否关闭本地通知的代码。 我在我的代码的多个部分使用这个 class 并且它工作正常,我的问题是我想通过NotificationsManager class 在 SwiftUI 的 onAppear 方法中调用getNotificationSettings但它总是变为零。 我知道它与getNotificationSettings是一个异步方法这一事实有关,但我不确定如何调用它并在 onAppear 方法上获得结果。

在以下代码中, notificationManager.notificationAuthorizationStatusonAppear方法中始终变为nil

知道如何在检查notificationAuthorizationStatus属性后立即在SwiftUIonAppear方法中调用reloadAuthorizationStatus()方法吗?

通知管理器 Class

class NotificationsManager: ObservableObject{
    @Published private(set) var notificationAuthorizationStatus: UNAuthorizationStatus?

    func reloadAuthorizationStatus() {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            DispatchQueue.main.async {
                self.notificationAuthorizationStatus = settings.authorizationStatus
            }
        }
    }
}

内容视图

struct ContentView: View {
    @StateObject private var notificationManager = NotificationsManager()

    var body: some View {
        NavigationView {
            Form {
                // textFields...
            }
            .onAppear(){
                notificationManager.reloadAuthorizationStatus() 
                // here the notificationAuthorizationStatus is always nil              
                switch notificationManager.notificationAuthorizationStatus{
                case .denied:
                    hasAuthorized = false
                default:
                    break
                }
            }
        }
    }
}

如果我在调用notificationAuthorizationStatus之前添加 1 秒的延迟,它会起作用,但我知道这是不对的,因为有时可能需要比一秒钟更长的时间才能得到结果。

延迟 1 秒呼叫

可行,但我认为这不是正确的做法

.onAppear(){
    notificationManager.reloadAuthorizationStatus()                
    let secondsDelay = DispatchTime.now() + 1
    DispatchQueue.main.asyncAfter(deadline: secondsDelay){
        switch notificationManager.notificationAuthorizationStatus{
        case .denied:
            hasAuthorized = false
        default:
            break
        }
    }
}

对于异步 function,您必须等到它完成才能使用它的任何结果。 使用completion处理程序是一种常见的方法。 所以试试这个方法:

func reloadAuthorizationStatus(completion: @escaping (Bool) -> ()) {  // <-- here
    UNUserNotificationCenter.current().getNotificationSettings { settings in
        DispatchQueue.main.async {
            self.notificationAuthorizationStatus = settings.authorizationStatus
            completion(true) // <-- here
        }
    }
}

ContentView

    .onAppear {
        notificationManager.reloadAuthorizationStatus { isDone in  // <-- here
            switch notificationManager.notificationAuthorizationStatus{
            case .denied:
                hasAuthorized = false
            default:
                break
            }
        }
    }

另一种方法是按原样保留代码,并使用此.onReceive

.onReceive(notificationManager.notificationAuthorizationStatus.publisher) { status in
    switch status{
    case .denied:
        hasAuthorized = false
    default:
        break
    }
}
.onAppear {
    notificationManager.reloadAuthorizationStatus()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM