[英]Calling an asynchronous method (getNotificationSettings) in the onAppear() method becomes nil - SwiftUI MVVM
I have a NotificationsManager
class to manage all notification-related code, including the code to check if the user has turned off local notifications.我有一个NotificationsManager
class 来管理所有与通知相关的代码,包括检查用户是否关闭本地通知的代码。 I use this class in multiple parts of my code and it works fine, my issue is that I want to call the getNotificationSettings
through the NotificationsManager
class in the onAppear method in SwiftUI but it always becomes nil.我在我的代码的多个部分使用这个 class 并且它工作正常,我的问题是我想通过NotificationsManager
class 在 SwiftUI 的 onAppear 方法中调用getNotificationSettings
但它总是变为零。 I know it has to do something with the fact that the getNotificationSettings
is an asynchronous method, but I'm not sure how to call it and get the result on the onAppear method.我知道它与getNotificationSettings
是一个异步方法这一事实有关,但我不确定如何调用它并在 onAppear 方法上获得结果。
In the following code, notificationManager.notificationAuthorizationStatus
always becomes nil
in the onAppear
method.在以下代码中, notificationManager.notificationAuthorizationStatus
在onAppear
方法中始终变为nil
。
Any idea how can I call the reloadAuthorizationStatus()
method in the onAppear
method in SwiftUI
and right after check the notificationAuthorizationStatus
property?知道如何在检查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
}
}
}
}
}
If I add a 1-second delay before calling the notificationAuthorizationStatus
it works but I know this is not right since sometimes it may take longer than just a second to get the results.如果我在调用notificationAuthorizationStatus
之前添加 1 秒的延迟,它会起作用,但我知道这是不对的,因为有时可能需要比一秒钟更长的时间才能得到结果。
Works but I don't feel it's the right thing to do可行,但我认为这不是正确的做法
.onAppear(){
notificationManager.reloadAuthorizationStatus()
let secondsDelay = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: secondsDelay){
switch notificationManager.notificationAuthorizationStatus{
case .denied:
hasAuthorized = false
default:
break
}
}
}
With an asynchronous function, you have to wait until it has finished before you can use any of its results.对于异步 function,您必须等到它完成才能使用它的任何结果。 Using a completion
handler is a common approach to do just that.使用completion
处理程序是一种常见的方法。 So try this approach:所以试试这个方法:
func reloadAuthorizationStatus(completion: @escaping (Bool) -> ()) { // <-- here
UNUserNotificationCenter.current().getNotificationSettings { settings in
DispatchQueue.main.async {
self.notificationAuthorizationStatus = settings.authorizationStatus
completion(true) // <-- here
}
}
}
and in ContentView
在ContentView
中
.onAppear {
notificationManager.reloadAuthorizationStatus { isDone in // <-- here
switch notificationManager.notificationAuthorizationStatus{
case .denied:
hasAuthorized = false
default:
break
}
}
}
Another approach is to leave your code as is, and use this .onReceive
:另一种方法是按原样保留代码,并使用此.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.