在 onAppear() 方法中调用异步方法 (getNotificationSettings) 变为 nil - SwiftUI MVVM
Calling an asynchronous method (getNotificationSettings) in the onAppear() method becomes nil - SwiftUI MVVM
我有一个 NotificationsManager
class 来管理所有与通知相关的代码,包括检查用户是否关闭本地通知的代码。我在我的代码的多个部分使用这个 class 并且它工作正常,我的问题是我想通过 NotificationsManager
class 在 onAppear 方法中调用 getNotificationSettings
SwiftUI 但它总是变成零。我知道这与 getNotificationSettings
是一个异步方法这一事实有关,但我不确定如何调用它并在 onAppear 方法上获得结果。
在下面的代码中,notificationManager.notificationAuthorizationStatus
总是在 onAppear
方法中变成 nil
。
知道如何在 SwiftUI
的 onAppear
方法中调用 reloadAuthorizationStatus()
方法,并在检查 notificationAuthorizationStatus
属性?
通知管理器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
}
}
}
对于异步函数,您必须等到它完成后才能使用它的任何结果。使用 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()
}
我有一个 NotificationsManager
class 来管理所有与通知相关的代码,包括检查用户是否关闭本地通知的代码。我在我的代码的多个部分使用这个 class 并且它工作正常,我的问题是我想通过 NotificationsManager
class 在 onAppear 方法中调用 getNotificationSettings
SwiftUI 但它总是变成零。我知道这与 getNotificationSettings
是一个异步方法这一事实有关,但我不确定如何调用它并在 onAppear 方法上获得结果。
在下面的代码中,notificationManager.notificationAuthorizationStatus
总是在 onAppear
方法中变成 nil
。
知道如何在 SwiftUI
的 onAppear
方法中调用 reloadAuthorizationStatus()
方法,并在检查 notificationAuthorizationStatus
属性?
通知管理器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
}
}
}
对于异步函数,您必须等到它完成后才能使用它的任何结果。使用 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()
}