[英]Firestore method in view model not invoking in SwiftUI onAppear method
[英]Calling an asynchronous method (getNotificationSettings) in the onAppear() method becomes nil - SwiftUI MVVM
我有一个NotificationsManager
class 来管理所有与通知相关的代码,包括检查用户是否关闭本地通知的代码。 我在我的代码的多个部分使用这个 class 并且它工作正常,我的问题是我想通过NotificationsManager
class 在 SwiftUI 的 onAppear 方法中调用getNotificationSettings
但它总是变为零。 我知道它与getNotificationSettings
是一个异步方法这一事实有关,但我不确定如何调用它并在 onAppear 方法上获得结果。
在以下代码中, notificationManager.notificationAuthorizationStatus
在onAppear
方法中始终变为nil
。
知道如何在检查notificationAuthorizationStatus
属性后立即在SwiftUI
的onAppear
方法中调用reloadAuthorizationStatus()
方法吗?
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 秒的延迟,它会起作用,但我知道这是不对的,因为有时可能需要比一秒钟更长的时间才能得到结果。
可行,但我认为这不是正确的做法
.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.